Java multi-threading & Safe Publication [已关闭]

2022-09-01 00:11:04

在阅读了“Java并发实践”和“实践中的OSGI”之后,我发现一个特定的主题非常有趣;安全发布。以下内容来自JCIP:

若要安全地发布对象,必须同时使对该对象的引用和该对象的状态对其他线程可见。正确构造的对象可以通过以下方式安全地发布:

  • 静态初始值设定项初始化对象引用。
  • 将对它的引用存储到可变字段中。
  • 将对它的引用存储到最终字段中。
  • 将对它的引用存储到由(同步)锁正确保护字段中。

我的第一个问题:有多少Java开发人员意识到这个(问题)?有多少现实世界的java应用程序真正遵循了这一点,这真的是一个真正的问题吗?我有一种感觉,99%的已实现JVM并不是那么“邪恶”,即线程不能保证(实际上它的实际(几乎)“不可能”)看到过时的数据,只是因为引用没有遵循上面的“安全发布习语”。


答案 1

从比例上讲,可以公平地说,很少有程序员充分理解同步和并发。谁知道现在有多少服务器应用程序管理金融交易,医疗记录,警察记录,电话等,这些应用程序充满了同步错误,基本上是偶然工作的,或者非常非常偶尔地失败(从未听说过有人接到幻像电话添加到他们的电话账单中?)原因从未真正调查或了解其底部。

对象发布是一个特殊的问题,因为它经常被忽视,而且编译器进行优化是非常合理的地方,如果你不知道它,可能会导致意外的行为:在JIT编译的代码中,存储一个指针,然后递增它并存储数据是一件非常合理的事情。你可能会认为这是“邪恶的”,但在低级别上,它确实是你所期望的JVM规范。(顺便说一句,我听说过在JRockit中运行的真实程序都存在这个问题 - 这不是纯粹的理论。

如果您知道您的应用程序存在同步错误,但在当前硬件上的当前JVM中没有行为异常,那么(a)恭喜;(b),现在是时候开始“冷静地走向消防出口”了,在需要升级太多组件之前修复代码并教育程序员。


答案 2

“这真的是一个真正的问题吗?”

是的,绝对可以。即使是最琐碎的Web应用程序也必须面对有关并发的问题。例如,Servlet 可由多个线程访问。

另一个问题是线程和并发很难正确处理。这几乎太难了。这就是为什么我们看到趋势像事务性内存一样出现,而像Clojure这样的语言有望使并发更容易处理。但在它们成为主流之前,我们还有很长的路要走。因此,我们必须用我们所拥有的做到最好。阅读JCiP是一个非常好的开始。