圖解 Java 多線程

Java內存模型(JMM)定義了:how and when different threads can see

values written to shared variables by other threads,

and how to synchronize access to shared variables when necessary.


圖解 Java 多線程


Java堆和棧中的對象存儲位置:


圖解 Java 多線程


Java內存模型與硬件模型:


圖解 Java 多線程


線程讀取主內存的數據到CPU緩衝中,當數據放在不同位置時,會有兩個問題:可見性與靜態條件


圖解 Java 多線程


A synchronized block in Java is synchronized on some object.

All synchronized blocks synchronized on the same object can only

have one thread executing inside them at the same time.

All other threads attempting to enter the synchronized block are blocked

until the thread inside the synchronized block exits the block.

The synchronized keyword can be used to mark four different types of blocks:

  1. Instance methods -> on the instance (object) owning the method
  2. Static methods -> on the class object of the class belongs to …
  3. Code blocks inside instance methods
  4. Code blocks inside static methods

Synchronized Instance methods(實例方法的同步):


圖解 Java 多線程


靜態方法的同步:


圖解 Java 多線程


代碼塊的同步:


圖解 Java 多線程


用jstack查看,同一個監視器對象只允許有一個線程訪問:


圖解 Java 多線程


實例方法的同步加上代碼塊this的同步,仍然針對同一個實例對象:


圖解 Java 多線程


自定義監視器對象:


圖解 Java 多線程


同一個實例對象的加鎖:


圖解 Java 多線程


不同實例對象的加鎖:


圖解 Java 多線程


Volatile keyword guarantees visibility of changes to variables across threads.

every read of a volatile variable will be

read from the computer’s main memory,

and not from the CPU cache.

every write to a volatile variable will be

written to main memory,

and not just to the CPU cache.

If Thread A writes to a volatile variable and Thread B subsequently reads the same volatile variable, then all variables visible to Thread A before writing the volatile variable, will also be visible to Thread B after it has read the volatile variable.

The reading and writing instructions of volatile variables cannot be reordered by the JVM. Instructions before and after can be reordered, but the volatile read or write cannot be mixed with these instructions. Whatever instructions follow a read or write of a volatile variable are guaranteed to happen after the read or write.

volatile變量不保證事務:


圖解 Java 多線程


volatile變量仍然會存在競態條件:


圖解 Java 多線程


volatile變量會禁止重排序:


圖解 Java 多線程


如果變量在volatile變量更新之後,不保證寫到主存:


圖解 Java 多線程


為了保證可見性,不需要為每個變量都定義為volatile類型:


圖解 Java 多線程


volatile變量是個內存屏障,在這之前和之後的指令可以重排序:


圖解 Java 多線程


本地線程的示例:


圖解 Java 多線程


下面的上圖沒有使用本地線程,下圖使用了本地線程:


圖解 Java 多線程


線程的信號量實現方式–busy waiting:


圖解 Java 多線程


或者可以用volatile變量:


圖解 Java 多線程


wait和notify的示例:


圖解 Java 多線程


notify與notifyAll的示例:


圖解 Java 多線程


等待線程有可能意外被喚醒,需要用while循環繼續判斷是否被喚醒線程notify:


圖解 Java 多線程


一次喚醒所有線程,或者每次一個個地喚醒:


圖解 Java 多線程


不同線程之間採用字符串作為監視器鎖,會喚醒別的線程:


圖解 Java 多線程


不同線程之間的信號沒有共享,等待線程被喚醒後繼續進入wait狀態:


圖解 Java 多線程


不同線程的等待與喚醒示例:


圖解 Java 多線程



分享到:


相關文章: