内容提要
Java中的volatile关键字解决多线程/多处理器环境下的可见性和指令重排问题。它保证了跨线程的内存一致性,通过禁止指令重排来保证程序正确性。
延伸解读
多核时代的内存一致性挑战
文章指出,单核时代内存模型是顺序一致性,所有线程看到的执行顺序一致。但多核时代,不同核心的缓存可能未及时同步到主内存,导致线程间读取到旧值。这种问题会破坏现有软件的正确性,因此需要新的内存模型和同步机制来保证跨线程的可见性。
两种解决方案的权衡
文章对比了两种方案:一是主内存保证顺序一致性,但所有读写穿透到主内存,缓存失效,性能大幅下降;二是硬件保证单线程顺序一致性,跨线程默认不保证,需通过同步原语(如内存屏障)来保证一致性。后者在保持单线程性能的同时,通过同步机制利用多核,成为现代处理器的选择。
volatile禁止重排的设计逻辑
文章解释了volatile读写之间不能重排序的原因:开发者声明volatile是为了让写操作对其他线程可见,若重排可能导致通知先于数据写入,使其他线程读取到未完成的数据。具体规则包括volatile写不能与之前的普通读写重排,volatile读不能与之后的普通读写重排,以确保线程间通信的正确性。
Q&A
Java中的volatile关键字有什么作用?
volatile关键字解决了多线程环境下的可见性和指令重排问题,确保跨线程的内存一致性。
为什么多核心处理器会导致可见性问题?
在多核心处理器中,一个核心的写入可能不会立即更新到主内存,导致其他核心读取到旧值,从而引发可见性问题。
Java如何保证多线程的内存一致性?
Java通过volatile语义提供可见性保证和禁止指令重排,确保多线程环境下的正确性。
使用volatile会影响程序性能吗?
使用volatile可以避免全同步操作内存的低效,且在单线程情况下几乎不降低性能,但在多线程情况下需要谨慎使用。
Java中的volatile与普通变量有什么区别?
volatile变量的读写操作不能被重排序,而普通变量的读写可以被重排序,这影响了多线程环境下的数据一致性。
如何在Java中使用volatile关键字?
在Java中,可以通过在变量声明前加上volatile关键字来使用,例如:volatile int count;