- 在共享內存的多處理器體系架構中,每一個處理器都擁有本身的緩存,而且按期地與主內存進行協調。
- 在不一樣的處理器架構中提供了不一樣級別的緩存一致性(Cache Coherence),
- 其中一部分只提供最小的保證,即容許不一樣的處理器在任意時刻從同一個存儲位置上看到不一樣的值。
- 操做系統、編譯器以及運行時(有時甚至包括應用程序)須要彌合這種在硬件能力與線程安全之間的差別。
java內存模型java
- 抽象出線程獨有的運行內存和共有的主存儲
- 爲了使java開發人員無須關心不一樣架構內存模型之間的差別,
- Java還提供了本身的內存模型,而且JVM經過在適當的位置上插入內存柵欄(內存屏障)來屏蔽在JVM與底層之平臺內存模型之間的差別。
- 線程中的變量什麼時候同步回到內存是不可預期的
- java內存模型規定,經過關鍵詞」synchronized「、」volatile「可讓java保證某些約束。
- 「volatile」 - 保證讀寫的都是主內存變量。
- 「synchronized」 - 保證在塊開始時,都同步主內存值到工做內存,而快結束時,將工做內存同步會主內存。
指令重排序::數組
public class PossibleReordering {
static int x = 0, y = 0;
static int a = 0, b = 0;
public static void main(String[] args) throws InterruptedException {
Thread one = new Thread(new Runnable() {
@Override
public void run() {
a = 1;
x = b;
}
});
Thread two = new Thread(new Runnable() {
@Override
public void run() {
b = 2;
y = a;
}
});
one.start();
two.start();
one.join();
two.join();
System.out.println("x:" + x + ",y:" + y);
}
}
- 執行結果,通常人可能認爲是1,1;真正的執行結果可能每次都不同。
- 拜JMM重排序所賜,JMM使得不一樣線程的操做順序是不一樣的,
- 從而致使在缺少同步的狀況下,要推斷操做的執行結果將變得更加複雜。
- 同步將限制編譯器和硬件運行時對內存操做重排序的方式。
鎖synchronized
- 鎖實現了對臨界資源的互斥訪問,是嚴格的排它鎖、互斥鎖。
- JVM規範經過兩個內存屏障(memory barrier)命令來實現排它邏輯。
- 內存屏障能夠理解成順序執行的一組CPU指令,徹底無視指令重排序。
- 類鎖(鎖是TestSTatic.class對象)、對象鎖
獨佔鎖
- 若是你不敢肯定該用什麼鎖,就用這個吧,在保證正確的前提下,後續在提升開發效率。
分拆鎖
- 若是將這些鎖請求分到更多的鎖上,就能有效下降鎖競爭程度。
- 因爲等待而被阻塞的線程將更少,從而可伸縮性將提升。
- 同時使用倆
分離鎖
- 在某些狀況下,能夠將鎖分解技術進一步擴展爲對一組獨立對象上的鎖進行分解,這種狀況稱爲鎖分段
- 例如ConcurrencyHashMap是有一個包含16個鎖的數組實現
- 鎖分段的劣勢在於:
- 與採用單個鎖來實現獨佔訪問相比,
- 要獲取多個鎖來實現獨佔訪問將更加困難而且開銷更高,
- 好比計算size、重hash。
分佈式鎖
- zookeeper,判斷臨時節點是否存在,存在就說明已經有人爭搶到鎖;
- 不存在就建立節點,代表擁有該鎖。
volatile
- volatile是比synchronized更輕量級的同步原語,
- volatile能夠修飾實例變量、靜態變量、以及數組變量(引用)。
- 被volatile修飾的變量,JVM規範規定,一個線程在修改完,另外的線程能讀取最新的值。
- 僅僅保證可見性,不保證原子性