在学习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会抛出那????