weixin_42363299 2010-04-16 11:26
浏览 250
已采纳

java编程思想 多线程部分有问题!

第四版 Critical sections部分:
You can also use explicit Lock objects to create critical sections:

[code="java"]//: 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 = 174035
pm2: Pair: x: 16, y: 16 checkCounter = 2608588
*///:~

[/code]

这段代码书里的,只是把synchronized 换成lock 实现,但是 我的运行结果每次会出现:
[color=red]---------- JAVA ----------
Exception in thread "pool-1-thread-4" Pair$PairValuesNotEqualException: Pair values not equal: x: 2, y: 1
at Pair.checkState(ExplicitCriticalSection.java:32)
at PairChecker.run(CriticalSection.java:101)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)[/color]
pm1: Pair: x: 11, y: 11 checkCounter = 3134
pm2: Pair: x: 12, y: 12 checkCounter = 1388632

谁能告诉我问什么这里有异常吗?按书里说是不会的!

哇 这个问题javaeye里居然有人问过,但没人回,郁闷啊,我问题跟他一摸一样[url=/topic/221693]http://www.iteye.com/topic/221693[/url]

  • 写回答

2条回答 默认 最新

  • waterdh1 2010-04-16 13:50
    关注

    这个问题的确比较迷惑人,作为老手我也足足想了1个多小时。
    1. 经过调试,发现出现异常的是ExplicitPairManager2,把pm.getPair().checkState();这段代码捕获下异常,并 System.out.println(pm.getClass().getSimpleName());即可定位。

    1. 比较下和ExplicitPairManager1的区别,1的方法上多了synchronized,其实有了这个关键字,其里面的lock,unlock有些多余,注释掉后运行也正常。

    2. 关键就在于synchronized上了,如果仅仅把synchronized当成一把锁来看待,这程序无论如何也会执行时候出现异常。为什么呢?原因如下:
      写入x,y的地方在increment方法上,而读取x,y在getPare()方法。理论上来说,要使得x=y,getPare()必须在等待increment执行结束之后被调用才能相等。从ExplicitPairManager2的代码中,可以发现lock只针对increament有效,没有排斥getPare()方法。
      但为什么加了synchronized关键字可以和getPare()互斥呢?私下以为java针对synchronized嵌套结构中做了优化,它们共享一把锁。
      [code="java"]
      public synchronized void increment() {
      lock.lock();
      try {
      p.incrementX();
      p.incrementY();
      try{
      Thread.sleep(1000);
      }catch(Exception e){}
      store(getPair()); //getPare()也是synchronized
      } finally {
      lock.unlock();
      }
      }
      [/code]

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示