求助一个简单的并发问题

it2025-04-04  20

最近在看Java编程思想,遇到一个问题://: concurrency/CriticalSection.java// Synchronizing blocks instead of entire methods. Also// demonstrates protection of a non-thread-safe class// with a thread-safe one.package concurrency;import java.util.concurrent.*;import java.util.concurrent.atomic.*;import java.util.*;class Pair { // Not thread-safe  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);    }  }  // Arbitrary invariant -- both variables must be equal:  public void checkState() {    if(x != y)      throw new PairValuesNotEqualException();  }}// Protect a Pair inside a thread-safe class: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() {    // Make a copy to keep the original safe:    return new Pair(p.getX(), p.getY());  }  // Assume this is a time consuming operation  protected void store(Pair p) {    storage.add(p);    try {      TimeUnit.MILLISECONDS.sleep(50);    } catch(InterruptedException ignore) {}  }  public abstract void increment();}// Synchronize the entire method:class PairManager1 extends PairManager {  public synchronized void increment() {    p.incrementX();    p.incrementY();    store(getPair());  }}// Use a critical section:class PairManager2 extends PairManager {  public void increment() {    Pair temp;    synchronized(this) {      p.incrementX();      p.incrementY();      temp = getPair();    }    store(temp);  }}class PairManipulator implements Runnable {  private PairManager pm;  public PairManipulator(PairManager pm) {    this.pm = pm;  }  public void run() {    while(true)      pm.increment();  }  public String toString() {    return "Pair: " + pm.getPair() +      " checkCounter = " + pm.checkCounter.get();  }}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();    }  }}public class CriticalSection {  // Test the two different approaches:  static void  testApproaches(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 + "\npm2: " + pm2);    System.exit(0);  }  public static void main(String[] args) {    PairManager      pman1 = new PairManager1(),      pman2 = new PairManager2();    testApproaches(pman1, pman2);  }} /* Output: (Sample)pm1: Pair: x: 15, y: 15 checkCounter = 272565pm2: Pair: x: 16, y: 16 checkCounter = 3956974*///:~这是其并发部分的一个同步示例,这个没问题,但另外一种用Lock的就有问题了//: concurrency/ExplicitCriticalSection.java// Using explicit Lock objects to create critical sections.package concurrency;import java.util.concurrent.locks.*;// Synchronize the entire method:class ExplicitPairManager1 extends PairManager {  private Lock lock = new ReentrantLock();  public synchronized void increment() {    lock.lock();    try {      p.incrementX();      p.incrementY();      store(getPair());    } finally {      lock.unlock();    }  }}// Use a critical section:class ExplicitPairManager2 extends PairManager {  private Lock lock = new ReentrantLock();  public void increment() {    Pair temp;    lock.lock();    try {      p.incrementX();      p.incrementY();      temp = getPair();    } finally {      lock.unlock();    }    store(temp);  }}public class ExplicitCriticalSection {  public static void main(String[] args) throws Exception {    PairManager      pman1 = new ExplicitPairManager1(),      pman2 = new ExplicitPairManager2();    CriticalSection.testApproaches(pman1, pman2);  }} /* Output: (Sample)pm1: Pair: x: 15, y: 15 checkCounter = 174035pm2: Pair: x: 16, y: 16 checkCounter = 2608588*///:~这样就在checkState的时候出问题了,在pman2的检查会抛出之前定义的异常,在增的过程中两个值不相等的时候作了check,貌似ReentrantLock没起作用,不知道是什么原因

转载于:https://www.cnblogs.com/mylordbin/p/8993519.html

相关资源:数据结构—成绩单生成器
最新回复(0)