可见性问题,只是说,非充分同步的情况下,允许出现,但并一定就得出现,如这个例子:
http://ifeve.com/concurrency-visibility/
又如这篇中http://ifeve.com/syn-jmm-visibility/提到的
在缺乏同步的情况下,模型还允许不一致的可见性。比如,得到一个对象的一个字段的最新值,同时得到这个对象的其他字段的过期的值。同样,可能读到一个引用变量的最新值,但读取到这个引用变量引用的对象的字段的过期值。
不管怎样,线程之间的可见性并不总是失效(指线程即使没有使用同步,仍然有可能读取到字段的最新值),内存模型仅仅是允许这种失效发生而已。因此,即使多个线程之间没有使用同步,也不保证一定会发生内存可见性问题(指线程读取到过期的值),java内存模型仅仅是允许内存可见性问题发生而已。在很多当前的JVM实现和java执行平台中,甚至是在那些使用多处理器的JVM和平台中,也很少出现内存可见性问题。共享同一个CPU的多个线程使用公共的缓存,缺少强大的编译器优化,以及存在强缓存一致性的硬件,这些都会使线程更新后的值能够立即在多线程之间传递。这使得测试基于内存可见性的错误是不切实际的,因为这样的错误极难发生。或者这种错误仅仅在某个你没有使用过的平台上发生,或仅在未来的某个平台上发生。这些类似的解释对于多线程之间的内存可见性问题来说非常普遍。没有同步的并发程序会出现很多问题,包括内存一致性问题。
又如这个例子中的:http://ifeve.com/doublecheckedlocking/#firstreason
也只是Symantec JIT的系统上重现了场景,其它平台未必能。
书上明确说明,第一段代码将无法停止,第二段代码可能会出现1,1的情况。但实际上并非书上所说。
While it may seem obvious that NoVisibility will print 42 , it is in fact possible that it will print zero, or never terminate at all!
NoVisibility could loop forever because the value of ready might never become visible to the reader thread. Even more strangely, NoVisibility could print zero because the write to ready might be made visible to the reader thread before the write to number, a phenomenon known as reordering.
原文的语气没那么强。同时也未指明在哪家的JVM以及什么版本上会出现。实际上,这完全是利用JVM应该提供的最小保障所做的理论分析。各厂家在实现JVM时可以提供更强的保障。