ReentrantLock 无效
代码取自think in java, jdk版本1.8,用 ReentrantLock 锁 在线程运行中取值会抛出PairValuesNotEqualException 异常,虽然最终结果x和y的值是一样的,用synchronized则不会出现这种问题,;
package concurrency.resource;
public class ExlicitCriticalSection {
public static void main(String[] args) throws Exception{
PairManager pman1=new ExpicitPairManager1(),
pman2=new ExpicitPairManager2();
CriticalSection.testApproaces(pman1,pman2);
}
}
package concurrency.resource;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class CriticalSection {
static void testApproaces(PairManager pman1, PairManager pman2){
ExecutorService exec= Executors.newCachedThreadPool();
PairManipulator pm1=new PairManipulator(pman1),pm2=new PairManipulator(pman2);
PairChecker pcheck1=new PairChecker(pman1),pcheck2=new PairChecker(pman2);
exec.execute(pm1);
exec.execute(pm2);
exec.execute(pcheck1);
exec.execute(pcheck2);
try{
TimeUnit.MILLISECONDS.sleep(500);
}catch (InterruptedException e){
System.out.println("Sleep interrupted");
}
System.out.println("pm1:"+pm1+"\n pm2"+pm2);
System.exit(0);
}
}
package concurrency.resource;
public 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++;}
public String toString(){
return "x:"+ x+",y:"+y;
}
public class PairValuesNotEqualException extends RuntimeException{
public PairValuesNotEqualException(){
super("Pair values not equal:"+Pair.this);
}
}
public synchronized void checkState(){
if(x!=y){
throw new PairValuesNotEqualException();
}
}
}
class:PairManager
package concurrency.resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
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 concurrency.resource;
import java.util.concurrent.locks.*;
public class ExpicitPairManager1 extends PairManager{
private Lock lock=new ReentrantLock();
public void increment(){
lock.lock();
try{
p.incrementX();
p.incrementY();
store(getPair());
}finally {
lock.unlock();
}
}
}
package concurrency.resource;
import java.util.concurrent.locks.*;
public class ExpicitPairManager2 extends PairManager {
private Lock lock=new ReentrantLock();
public void increment(){
lock.lock();
try{
p.incrementX();
p.incrementY();
store(getPair());
}finally {
lock.unlock();
}
}
}
package concurrency.resource;
public class PairChecker implements Runnable {
private PairManager pm;
public PairChecker(PairManager pm){
this.pm=pm;
}
public void run(){
while (true){
pm.checkCounter.incrementAndGet();
pm.getPair().checkState();
// System.out.println(pm.getPair().toString());//这边输出的数据x和y又一样
}
}
}