java - 空的 synchronized(this){} 对线程之间的内存可见性有什么意义吗?

标签 java concurrency synchronized volatile memory-model

我在 StackOverflow 上的一条好评评论中读到了这篇文章:

But if you want to be safe, you can add simple synchronized(this) {} at the end of you @PostConstruct [method]

[注意变量不是易变的]

我在想 happens-before 只有在 synchronized block 中同时执行写入和读取时才会强制执行,或者至少读取是 volatile 的。

引用的句子正确吗?空的 synchronized(this) {} block 是否会将当前方法中更改的所有变量刷新到“一般可见”内存?

请考虑一些场景

  • 如果第二个线程从不调用 this 上的锁怎么办? (假设第二个线程以其他方法读取)。请记住,问题是关于:将更改刷新到其他线程,而不是为其他线程提供一种方式(同步)来轮询原始线程所做的更改。在 Spring @PostConstruct 上下文中,其他方法中的不同步也很可能 - 正如原始评论所说。

  • 是否仅在另一个线程的第二次和后续调用中强制更改的内存可见性? (请记住,此同步块(synchronized block)是我们方法中的最后调用)- 这会将这种同步方式标记为非常糟糕的做法(第一次调用中的值过时)

最佳答案

很遗憾,关于 SO 的大部分内容,包括该线程中的许多答案/评论,都是错误的。

此处适用的 Java 内存模型中的关键规则是:在给定监视器上的解锁操作在此之前发生在同一监视器上的后续锁定操作。如果只有一个线程获得了锁,它就没有任何意义。如果虚拟机可以证明锁对象是线程受限的,它可以忽略它可能发出的任何栅栏。

您强调的引用假设释放锁充当完整的围栏。有时这可能是真的,但你不能指望它。所以你的怀疑问题是有根据的。

Java Concurrency in Practice ,第 16 章了解更多关于 Java 内存模型的信息。

关于java - 空的 synchronized(this){} 对线程之间的内存可见性有什么意义吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23906727/

相关文章:

java - JLabel 在 ActionListener 中没有被正确识别

java - JFileChooser .txt 扩展名

java - Spring @Async 和同步

multithreading - Jackrabbit 和并发修改

java - 管理多个锁

java - jfreecharts中如何调整x、y轴线

java - 有什么办法可以防止字段在 jackson 中反序列化吗?

java - 使用同步方法的类的多个实例

java - Collections.synchronizedList 中需要客户端锁定

静态变量上的 Java 同步方法