我有一个很特别的问题,我找不到答案。
正如我们所知道的,在synchronized块中的入口,一个线程对其作用域中的所有共享(非本地)变量执行重读。某些底层体系结构的示例:如果线程A更新RAM中对象的状态,则进入同步块的线程B将看到更改。在退出synchronized块时也会发生类似的事情:线程将其作用域中的所有内容都刷新到内存中,以便其他线程可以看到它。这些都是JVM可见性的基本保证,也是在出现强制执行规则之前发生的情况。
但是,在语义上,使用wait()或notify()的代码是否也做了所有这一切并不十分清楚:毕竟,它没有明确地输入或离开synchronized块。
问题如下:
JVM是否确保对notify()入口上其他线程的更改的可见性? JVM是否确保在上其他线程中所做的更改的可见性?
wait()上其他线程的更改的可见性?发布于 2020-05-02 16:32:58
正如我们所知,在同步块的入口,线程对其作用域中的所有变量进行重新读取;也就是说,如果线程A更新RAM中的对象的状态,进入同步块的线程B将看到更改。
第一部分是不正确的。并不是所有的变量都是重读的。局部变量是不确定的。它们不需要重读,因为它们在另一个线程中是不可见的。
正确的语句是编译器将确保线程A在退出该块之前编写的共享变量在B进入该块后对线程B可见。条件是A和B在同一个互斥对象上同步,并且同时A(或其他一些线程)没有覆盖它们。
没有与notify或notifyAll关联的显式内存语义。然而,wait将导致互斥体被释放并(通常)重新获得.在与其他线程建立关系之前,发布和重新获取就已经发生了。
,请您详细说明与释放和获取锁有关的确切语义吗?它们是否与输入同步块相同?
让我们假设我们只有两个线程,A和B,以及一个互斥线程。
还请记住,只有持有锁的线程才能调用wait和notify。
L.wait().
L.notify()
L.wait()调用返回。在这里重要的边缘之前发生的是介于2到3之间,然后是5到6之间。
如果涉及多个线程,则可以通过在关系之前链接发生的情况来分析行为。但是在释放互斥锁的线程和下一个线程之间只有一个直接HB来获取它.无论如何都行。
所以,你的问题的答案是:
( 1) & 2)是的,假设另一个线程正确地使用了synchronized。( 3)不。可见点是当互斥对象由名为notify()的线程释放时。
请注意,内存屏障、刷新等是实现细节。事实上,编译器可以自由地实现发生的语义--在它想要的任何方式之前。包括(假设)优化清除内存刷新,如果它们是不必要的。
最好(海事组织)忽略这些实施细节,只考虑发生-之前的关系。
有关发生之前发生的更多信息,请阅读:
https://stackoverflow.com/questions/61562542
复制相似问题