在Java Memory Model中关系之前发生

时间:2014-11-07 22:47:31

标签: java java-memory-model

我对Java内存模型有疑问。

在以下场景中: 姓名:a = 0; b = 0;

T1:
    a = 1;
    l.lock();
    b = 1;
    l.unlock();

T2:
    l.lock();
    read b;
    l.unlock();
    read a;

我可以说,b读取的T2的值是1,那么a读取的T2的值必须是{{1} }}?

根据我的理解,1中的unlock会将T1a的值与主内存和b中的lock一起清除确保T2read a都可以获得最新值。

我是对的吗?

编辑:我刚刚指定它们被锁定在同一个锁上。

2 个答案:

答案 0 :(得分:2)

  

如果T2读取的b的值是1,那么T2的读取值是否必须为1?

是。它得到了保证。操作可以将移动到同步块中,但不能输出。请参阅Jeremy Mansons博客文章Roach Motels and The Java Memory Model

这意味着,虽然read a可以在unlock之前向上移动(并且由于指令重新排序而高于read b),但它永远不会超过lock指令T2

相同的推理适用于a = 1:它可以向下移动到同步块(由于指令重新排序而在b = 1之下),但不会传递unlock指令。

但是,如果我们交换这样的说明,它们都会被锁定,这意味着如果T21读取b,那么T1已经写了1b

答案 1 :(得分:0)

我从http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html找到了一些有用的信息。

在同步做什么?部分,它说:

'同步确保线程之前或在同步块期间的内存写入以可预测的方式显示给在同一监视器上同步的其他线程。在我们退出synchronized块之后,我们释放了监视器,它具有将缓存刷新到主内存的效果,因此该线程所做的写操作对其他线程是可见的。在我们进入同步块之前,我们获取监视器,它具有使本地处理器高速缓存无效的效果,以便从主存储器重新加载变量。然后,我们将能够看到之前版本中显示的所有写入内容。'

'这意味着在退出同步块之前对线程可见的任何内存操作在进入受同一监视器保护的同步块后对任何线程都是可见的,因为所有内存操作都在发布之前发生,并且释放发生在获得之前。'