ReentrantLock 无效

xjpssh 2017-05-31 07:30:19
代码取自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又一样
}
}
}
...全文
6580 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
kk1924 2020-12-23
  • 打赏
  • 举报
回复
引用 2 楼 捏造的信仰 的回复:
楼主要学会贴代码:

正确的代码是这样的:
public class Hello {
private String name;
}



楼主要学会贴代码
捏造的信仰 2020-12-16
  • 打赏
  • 举报
回复
楼主要学会贴代码:

正确的代码是这样的:
public class Hello {
private String name;
}
undertaIe 2020-12-13
  • 打赏
  • 举报
回复
重写ExpicitPairManager1和2的getPair方法
public Pair getPair() {
        // Make a copy to keep the original safe:
        lock.lock();
        try{
            Pair pp = new Pair(p.getX(), p.getY());
            return pp;
        }finally {
            lock.unlock();
        }
    }

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧