猿问

是否可以使用可见性保证而不是完全锁定来以线程安全的方式访问共享状态?

Java Concurrency in Practice 声明如下:

当线程 A 执行一个同步块,随后线程 B 进入一个由同一个锁保护的同步块时,在释放锁之前对A 可见的变量值保证在获取锁时对 B 可见。换句话说,当 B 执行由同一锁保护的同步块时,A 在同步块之前所做的一切对 B 都是可见的。没有同步,就没有这样的保证。

同样的逻辑适用于 volatile 变量:

volatile 变量的可见性影响超出了 volatile 变量本身的值。当线程 A 写入一个 volatile 变量,随后线程 B 读取同一个变量时,在写入 volatile 变量之前对 A 可见的所有变量的值在读取该 volatile 变量后对 B 可见。

从描述中可以清楚地看出,当您需要访问某些共享状态时,您可以使用这种可见性效果来实际替换(或限制使用)传统锁。在图中的示例中,您可以看到线程 B 可以安全地读取变量y,即使它在同步块外的线程 A 中发生了更改。

因此,当您在线程上锁定之前更改某些共享状态时使用它是否安全visibility guarantee,然后获取锁定,做某事(或者什么都不做,我猜),释放锁然后在另一个线程中获得相同的锁锁定,释放它,然后安全地从第一个线程中更新的共享变量中读取最新值?


HUWWW
浏览 108回答 2
2回答

扬帆大鱼

引用语句中有一个关键部分:volatile 变量的可见性影响超出了 volatile 变量本身的值。当线程 A 写入一个 volatile 变量,随后线程 B 读取同一个变量时,在写入 volatile 变量之前对 A 可见的所有变量的值在读取 volatile 变量后对 B 可见。虽然这显然是正确的,但您在这里得到了关于 A 写先于 B 阅读的条件。然而,如果不锁定,就无法保证读/写的顺序——这就是重点。所以你不能用 volatiles 替换每个同步,因为它不会产生相同的结果。

白板的微信

是的,您可以visibility guarantee通过使用或任一形式的锁定以描述的方式获得,但volatile仅此而已。具体来说,您不会获得相互访问和原子性。synchronized另请参阅 JLS中有关 JVM的内存模型和happens-before关系的部分,以获得更多细节和深度。
随时随地看视频慕课网APP

相关分类

Java
我要回答