在多執行緒這一系列中,不去探究記憶體模型的底層
在在現代多核心處理器中,每個處理器都有自己的緩存,定期的與主記憶體進行協調;
想要確保每個處理器在任意時刻知道其他處理器正在進行的工作,將需要很大的開銷;且通常是沒必要的
我們只有在需要跨線程共享資料時,才需要知道資訊;而在JAVA中就是透過正確的同步來實現
如下:判斷輸出的值將十分困難
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,但是我沒必要明確的做出選擇
JMM為程序中所有的操作定義了一個偏序關係,稱之為Happens-Before;要想保證執行B操作的線程看到執行A操作的線程的結果,無論AB是否在同一線程,必須滿足Happens-Before關係,否則JVM就會對其重排序
#
#
#如:加鎖操作,就可以預知執行順序,多個執行緒之間就符合Happens-Before,不加鎖則無法判斷執行緒之間的調度,
真正原因:發布一個共享對象 和 在另一個線程中訪問該對象之間沒有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 publicationreturn resource; }static class Resource { } }
#
以上是什麼是記憶體模型,為什麼需要它?的詳細內容。更多資訊請關注PHP中文網其他相關文章!