首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java对象在多个锁下的可见性

java对象在多个锁下的可见性
EN

Stack Overflow用户
提问于 2014-06-28 17:30:04
回答 1查看 177关注 0票数 1

这是我面临的问题。在运行下面的代码时,我有时会在打印B的内容时得到陈旧的数据,我真的不明白为什么会发生这种情况,因为更新和接收B的内容受到B的锁的保护。

注意,在对B的更新过程中,A和B的锁都保持着。在访问B的内容时,只持有一个锁。

还请注意,B.updated()不是同步的,但我不认为这是问题所在,因为在访问B的内容之前,我要确保将更新的计数器设置为2。

代码语言:javascript
复制
class B {
  Object data
  int updated = 0

  // get and set protected by B's monitor
  synchronized Object getData() {
    return data;
  }
  synchronized setData(Object d) {
    data = d;
    updated += 1;
  }
  // deliberately not synchronized
  int updated() { return updated; }
}

class A {
    B b
    A() {
        new Thread t = new Thread(new UpdaterThread());
        t.start();
    }

   // when B is updated both A and B monitors are held
    synchronized String setB(Object data) {
      b.setData(data);
   }

   class UpdateThread implements Runnable {
     public void run() {
       // updating B to new Value
       setB("B2");
     }
   }
}

public static void main(String[] _) {
   B b = new B();  
   b.setData("B1");
   A a = new A();
   while (b.updated() == 1) {
     // wait for updated to reach 2
   } 
   println(b.getData());  // prints "B1" sometimes, but very rarely.
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-28 17:36:44

您期望代码是顺序一致。但是,如果代码中没有数据竞争,Java只保证顺序一致性。

还请注意,B.updated()不是同步的,但我不认为这是问题所在,因为在访问B的内容之前,我要确保将更新的计数器设置为2。

这就是问题所在。在更新的变量上有一个数据竞赛,因为一个线程向它写入数据,而另一个线程在没有任何同步的情况下从它读取。

如果将变量设置为volatile,则代码将工作,因为volatile变量上不存在数据竞争。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24469302

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档