Javamultithreading和安全发布

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

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

  • 静态初始化器初始化对象引用。
  • 将引用存储到一个易变的字段中。
  • 将参考存储在最终字段中。
  • 将引用存储到由( 同步 )locking正确保护的字段中。

我的第一个问题:有多lessJava开发人员知道这个(问题)? 有多less真实世界的Java应用程序真的跟着这个,这真的是一个真正的问题? 我有一种感觉,99%的已实现的JVM在那里没有那个“邪恶”,即一个线程是不能保证的(实际上它实际上(几乎)“不可能”)看到陈旧的数据只是因为引用没有跟随上面的“安全出版习语”。

按比例而言,很less有程序员充分理解同步和并发性。 谁知道现在有多less个服务器应用程序正在pipe理财务交易,病历,警察logging,电话等等,这些应用程序都是同步错误,并且实际上是偶然的工作,或者偶尔会失败(从来没有听说过任何人会得到一个幻像电话添加到他们的电话帐单?)的原因是从来没有真正看过或得到的底部。

对象发布是一个特殊的问题,因为它经常被忽视,而且这是一个编译器进行优化的地方,如果你不知道它会导致意想不到的行为:在JIT编译的代码中,存储一个指针,然后递增和存储数据是一个非常合理的事情。 你可能会认为这是“邪恶的”,但是在一个较低的层次上,你真正期望的是JVM规范。 (顺便说一句,我听说JRockit上运行的真正的程序正在遭受这个问题的困扰 – 这不完全是理论上的)。

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

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

是的,一点没错。 即使是最琐碎的Web应用程序也必须面对围绕并发的问题。 例如,Servlet由多个线程访问。

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

首先“安全出版”并不是一个成语(IMO)。 它来自语言。

出现不安全的问题,例如使用NIO。

大多数Java代码写得非常糟糕。 线程代码显然比一般的业务线代码更难。

这不是一个“邪恶”的问题。 这一个真正的问题,随着多核架构在未来几年的崛起将会变得更加明显。 由于不正确的同步,我看到了非常真实的生产错误。 而要回答你的另一个问题,我会说很less有程序员知道这个问题,即使在其他“好”的开发者中也是如此。

我想说的是,很less有程序员离开这个问题。 你看到的最后一个代码示例是什么时候使用volatile关键字? 然而,大多数其他条件提到 – 我只是理所当然的最佳做法。

如果开发者完全忽略这些条件,他们将很快遇到multithreading错误。

我的经验(在很多不同types的环境中进行短期的咨询和大多数应用程序的咨询)都与这种直觉相一致 – 我从来没有看到整个系统的架构能够很好地解决这个问题(好吧,我也差不多从来没有见过一个完整的系统架构)。 我和非常less的开发人员一起工作,对线程问题有很好的了解。

特别是对于networking应用程序,你经常可以逃避这一点,或者至less似乎摆脱它。 如果你有基于spring的实例pipe理你的对象创build和无状态的servlet,你可以经常假装没有同步这样的事情,这是许多应用程序结束的地方。 最终有人开始把一些共享状态放在它不属于的地方,3个月后有人注意到一些奇怪的间歇性错误。 对于很多人来说,这通常是“够好的”(只要你不写银行交易)。

有多lessjava开发人员知道这个问题? 很难说,因为它很大程度上取决于你在哪里工作。

Interesting Posts