2 u010353960 u010353960 于 2016.03.10 10:09 提问

关于JAVA编程思想中synchronized和ReentrantLock

在学习JAVA编程思想并发一章时,关于synchronized和ReentrantLock的例子运行
结果与书中不一致。代码如下:

 package thinking.in.java.chapter21;

class Pair {
    private int x,y;
    public Pair(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public Pair() {
        this(0,0);
    }
    public int getX(){
        return x;
    }
    public int getY(){
        return y;
    }
    public void incrementX(){x++;}
    public void incrementY(){y++;}
    @Override
    public String toString() {
        return "x=" + x + ", y=" + y;
    }
    public class PairValuesNotEqualException extends RuntimeException {
        public PairValuesNotEqualException() {
            super("Pair values not equal: " + Pair.this);
        }
    }
    public void checkstate(){
        if(x != y)
            throw new PairValuesNotEqualException();
    }
}

package thinking.in.java.chapter21;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public abstract class PairManager {
    AtomicInteger checkCounter = new AtomicInteger(0);
    protected Pair p = new Pair();
    private List<Pair> storage = 
            Collections.synchronizedList(new ArrayList<Pair>());
    public synchronized Pair getPair(){
        return new Pair(p.getX(),p.getY());
    }

    protected void store(Pair p){
        storage.add(p);
        try{
            TimeUnit.MILLISECONDS.sleep(50);
        }catch(InterruptedException e){}
    }
    public abstract void increment();

}

package thinking.in.java.chapter21;

public class PairChecker implements Runnable {

    private PairManager pm;
    public PairChecker(PairManager pm) {
        this.pm = pm;
    }

    @Override
    public void run() {
        while(true){
            pm.checkCounter.incrementAndGet();
            pm.getPair().checkstate();
        }

    }

}

package thinking.in.java.chapter21;

public class PairManager1 extends PairManager {

    @Override
    public synchronized void increment() {
        p.incrementX();
        p.incrementY();
        store(getPair());
    }
}

package thinking.in.java.chapter21;

public class PairManager2 extends PairManager {

    @Override
    public void increment() {
        Pair temp;
        synchronized (this) {
            p.incrementX();
            p.incrementY();
            temp = getPair();
        }
        store(temp);

    }

}

package thinking.in.java.chapter21;

public class PairManipulator implements Runnable {
    private PairManager pm;
    public PairManipulator(PairManager pm) {
        this.pm = pm;
    }
    @Override
    public void run() {
        while(true)
            pm.increment();
    }
    @Override
    public String toString() {
        return "Pair: " + pm.getPair() +
                " checkerCounter = " + pm.checkCounter.get();
    }

}

package thinking.in.java.chapter21;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class CriticalSection {
    static void testApproaches(PairManager pman1,
            PairManager pman2){
        ExecutorService exec = Executors.newCachedThreadPool();
        PairManipulator 
            pm1 = new PairManipulator(pman1),
            pm2 = new PairManipulator(pman2);
        PairChecker
            pchecker1 = new PairChecker(pman1),
            pchecker2 = new PairChecker(pman2);
        exec.execute(pm1);
        exec.execute(pm2);
        exec.execute(pchecker1);
        exec.execute(pchecker2);
        try{
            TimeUnit.MILLISECONDS.sleep(1000);
        }catch(InterruptedException e){
            System.err.println("Sleep interrupted");
        }
        System.out.println("pm1: " + pm1 + "\npm2: " + pm2);
        System.exit(0);
    }
    public static void main(String[] args) {
        PairManager
            pman1 = new PairManager1(),
            pman2 = new PairManager2();
        testApproaches(pman1, pman2);
    }
}

package thinking.in.java.chapter21;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ExplicitPairManager1 extends PairManager {
    private Lock lock = new ReentrantLock();
    @Override
    public void increment() {
        lock.lock();
        try{
            p.incrementX();
            p.incrementY();
            store(getPair());
        }finally{
            lock.unlock();
        }

    }

}

package thinking.in.java.chapter21;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ExplicitPairManager2 extends PairManager {

    private Lock lock = new ReentrantLock();
    @Override
    public void increment() {
        lock.lock();
        Pair temp;
        try{
            p.incrementX();
            p.incrementY();
            temp = getPair();
        }finally{
            lock.unlock();
        }
        store(temp);
    }

}

package thinking.in.java.chapter21;

public class ExolicitCritialSection {
    public static void main(String[] args) {
        PairManager
            pman1 = new ExplicitPairManager1(),
            pman2 = new ExplicitPairManager2();
        CriticalSection.testApproaches(pman2, pman1);
    }
}

按照书中所说,ExolicitCritialSection和CriticalSection都不应该抛出PairValuesNotEqualException异常,可是ExolicitCritialSection中的两个线程都抛出了该异常,
个人分析在进行increment的时候,虽然是同步操作,可是在进行PairChecker时checkstate方法并未同步,他可以访问Pair对象中的X和Y值,所以按照书中的列子感觉都应该抛出PairValuesNotEqualException异常才对,为什么只有ExolicitCritialSection会抛出那????

2个回答

u010353960
u010353960   2016.03.10 10:13

求并发高手解答啊!!

u010353960
u010353960   2016.03.10 10:30

没人能解答吗?还是代码太多了啊

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!