在多線程這一系列中,不去探究內存模型的底層緩存
在現代多核處理器中,每一個處理器都有本身的緩存,按期的與主內存進行協調;安全
想要確保每一個處理器在任意時刻知道其餘處理器正在進行的工做,將須要很大的開銷;且一般是不必的多線程
咱們只有在須要跨線程共享數據時,才須要知道信息;而在JAVA中就是經過正確的同步來實現app
以下:判斷輸出的值將十分困難spa
public class PossibleReordering { static int x = 0, y = 0; static int a = 0, b = 0; /** * 判斷輸出值將會很是困難: * 1:多線程之間的切換,致使可能的輸出值:(0,1)(1,0)(1,1) * 2.指令重排序:one線程如a=1和x=b之間重排序,x=b(0),而後other線程被調度執行y=a(0),將致使(0,0) */ public static void main(String[] args) throws InterruptedException { Thread one = new Thread(new Runnable() { public void run() { a = 1; x = b; } }); Thread other = new Thread(new Runnable() { public void run() { b = 1; y = a; } }); one.start(); other.start(); one.join(); other.join(); System.out.println("( " + x + "," + y + ")"); } }
偏序關係:反對稱、自反和傳遞屬性;可是對於任意的兩個元素A和B,並不必定知足A偏向B或B偏向A的關係線程
如:A和B之間我更偏向B,可是我不必明確的作出選擇code
JMM爲程序中全部的操做定義了一個偏序關係,稱之爲Happens-Before;要想保證執行B操做的線程看到執行A操做的線程的結果,不管AB是否在同一線程,必須知足Happens-Before關係,不然JVM就會對其重排序對象
如:加鎖操做,就能夠預知執行順序,多個線程之間就符合Happens-Before,不加鎖則沒法判斷線程之間的調度,blog
真正緣由:發佈一個共享對象 和 在另外一個線程中訪問該對象之間沒有Happens-Before關係;因爲指令重排序,致使對象沒有正確構建則被髮布排序
public class UnsafeLazyInitialization { private static Resource resource; /** * 除了竟態條件問題檢查後執行,還有不安全發佈的問題 * 如:一個線程A進來,看到resource爲null,則實例化並返回;另外一個線程B進來看到resource不爲null直接返回 * 若是在線程A中對resource進行了修改,則可能在線程B中看不到resource的正確狀態 */ public static Resource getInstance() { if (resource == null) resource = new Resource(); // unsafe publication return resource; } static class Resource { } }