在什么情况下可能一个空同步框实现正确的穿语?
-
22-08-2019 - |
解决方案
一个空同步块将等待,直到没有其他人正在使用该同步器。这可能是你想要什么,而是因为你没有在synchronized块保护后面的代码,没有从修改过什么是你在等待的同时运行后续代码阻止其他人。这是几乎从来没有你想要的东西。
其他提示
先前的答案未能强调,最有用的东西有关空 synchronized
模块:他们可以确保能见度的变量变化和其他行动跨线。作为 jtahlborn 指示,同步规定,"记忆屏障"上编译器,迫使它冲洗和刷新其缓存。但我没找到这里的"蛇讨论了"这,所以我写了回答我自己。
int variable;
void test() // This code is INCORRECT
{
new Thread( () -> // A
{
variable = 9;
for( ;; )
{
// Do other stuff
}
}).start();
new Thread( () -> // B
{
for( ;; )
{
if( variable == 9 ) System.exit( 0 );
}
}).start();
}
上述程序是不正确的。值的变量可能会缓存在本地的在线A或B或两者。所以,B可能永远不会阅读值的9个写道,和可能因此循环永远。
做一个变量的变化可见的在线程通过使用空 synchronized
块
一个可能的修正添加一个 volatile
(有效地"没有高速缓冲存储器")修改的变量。有时候,这是效率低下,然而,因为它完全禁止缓存的变量。空 synchronized
块,另一方面,不要禁止缓存。他们所要做的就是力的高速缓存同步主要存在某些关键点。例如:*
int variable;
void test() // Corrected version
{
new Thread( () -> // A
{
variable = 9;
synchronized( o ) {} // Flush to main memory
for( ;; )
{
// Do other stuff
}
}).start();
new Thread( () -> // B
{
for( ;; )
{
synchronized( o ) {} // Refresh from main memory
if( variable == 9 ) System.exit( 0 );
}
}).start();
}
final Object o = new Object();
如何在存储器模型的担保的能见度
两个线程必须同步上相同的对象,以便保证的可见性。这一保证在于 Java存储器模型, ,特别是在该规则,"解开行动监测m 进行同步-有 随后的所有锁行动对m"并由此 发生之前 这些行动。因此,一个是解锁的o显示在它的尾巴 synchronized
框发生之前B的后续锁定在其块。(注意,这是个奇怪的尾巴-头订的有关这就解释了为什么该机构可以是空的。) 给也一个人写信之前对其解和B的锁之前读的关系必须延伸到涵盖编写和阅读: 编写发生之前读.这是至关重要的,扩展关系,使经修订的程序正在存储器模型。
我认为这是最重要的使用对空 synchronized
块。
* 我说的就好像是一个问题的处理缓存 因为我认为这是一个有用的方式观看。事实上,作为亚历山大*杜宾斯基发表了评论意见,所有现代的处理器是cache-连贯一致。这种情况发生之前的关系更多是关于什么的编译器是允许这样做,而不是CPU。'
它曾经是,说明书暗示某些存储器屏障操作发生的情况。然而,该规范已经改变,原来的规范从未正确实施。它可被用于等待另一个线程来解除锁定,但协调的是,其他线程已经获取锁定将是棘手的。
同步确一点点多只是等待,同时不优雅的编码这可能达到的效果所必需的。
从 http://www.javaperformancetuning.com/news/qotm030.shtml
- 在线取得该锁上的监视对象的这种(假设监测是解锁,否则线等待,直到的监测是解锁).
- 螺纹记忆冲其所有的变量,即它具有其所有的变量有效地读取从"主要的"存储器(Jvm可以使用肮脏组,以优化这个所以,只有"脏"变量的刷新,但这在概念上是相同的。见第17.9Java语言的规范)。
- 代码块执行(在这种情况下设置返回值以目前价值i3,这可能只是被重置的,从"主要的"存储器)。
- (任何更改变通常会现在可以写出来"主要"记忆,但是对于geti3()我们没有变化。)
- 线释放锁上的监视对象这一点。
对于在深入探讨Java的内存模型,看看从谷歌的系列的编程语言中的高级主题“这个视频: http://www.youtube.com/watch?v=1FX4zco0ziY
它给什么样的编译器可以(通常在理论上,但有时在实践中)做你的代码一个非常好的概述。基本的东西任何严重的Java程序员!