Java內存模型(Java Memory Model ,JMM)

Java內存模型(Java Memory Model ,JMM)

JMM是和多線程相關的,他描述了一組規則或規範,這個規範定義了一個線程對共享變量的寫入時對另一個線程是可見的。目的是解決由於多線程通過共享內存進行通信時,存在的原子性、可見性(緩存一致性)以及有序性問題。

原子性

線程是CPU調度的基本單位。CPU有時間片的概念,會根據不同的調度算法進行線程調度。所以在多線程場景下,就會發生原子性問題。因爲線程在執行一個讀改寫操作時,在執行完讀改之後,時間片耗完,就會被要求放棄CPU,並等待重新調度。這種情況下,讀改寫就不是一個原子操作,即存在原子性問題。

緩存一致性

在多核CPU,多線程的場景中,每個核都至少有一個L1 緩存。多個線程訪問進程中的某個共享內存,且這多個線程分別在不同的核心上執行,則每個核心都會在各自的caehe中保留一份共享內存的緩衝。由於多核是可以並行的,可能會出現多個線程同時寫各自的緩存的情況,而各自的cache之間的數據就有可能不同。

有序性

由於處理器優化和指令重排等,CPU還可能對輸入代碼進行亂序執行,比如load->add->save 有可能被優化成load->save->add 。這就是有序性問題。

所以,爲了保證併發編程中可以滿足原子性、可見性及有序性。有一個重要的概念,那就是——內存模型。

Java內存模型的實現

原子性

在Java中,爲了保證原子性,在Java中可以使用synchronized來保證方法和代碼塊內的操作是原子性的。

可見性

Java內存模型是通過在變量修改後將新值同步回主內存,在變量讀取前從主內存刷新變量值的這種依賴主內存作爲傳遞媒介的方式來實現的。
Java中的volatile關鍵字提供了一個功能,那就是被其修飾的變量在被修改後可以立即同步到主內存,被其修飾的變量在每次是用之前都從主內存刷新。因此,可以使用volatile來保證多線程操作時變量的可見性。
除了volatile,Java中的synchronized和final兩個關鍵字也可以實現可見性。

有序性

在Java中,可以使用synchronized和volatile來保證多線程之間操作的有序性。實現方式有所區別:

volatile關鍵字會禁止指令重排。synchronized關鍵字保證同一時刻只允許一條線程操作。

好像synchronized關鍵字是萬能的,他可以同時滿足以上三種特性,這其實也是很多人濫用synchronized的原因。

但是synchronized是比較影響性能的,雖然編譯器提供了很多鎖優化技術,但是也不可以過度使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章