Java中的併發機制依賴於JVM的實現和CPU指令,接下來咱們深刻底層探索Java併發機制的實現原理。java
Java中容許線程訪問共享變量,爲了保證共享變量可以一致的被更新,線程應該確保經過排他鎖單獨的獲取這個變量。Java中就提供了volatile,若是一個字段被聲明成volatile,在java線程內存模型確保全部的線程看到的這個變量的值都是一致的。緩存
volatile是一種輕量級synchronized,並且執行的成本比較低,沒有上下文切換的消耗。volatile修飾的共享變量在進行寫操做的時候,在多處理器下會引發兩件事:併發
(1)、將當前處理器緩存行的數據寫會到系統內存性能
(2)、這個回寫操做會使得CPU中其餘的處理器緩存了該地址的數據無效。優化
對於高速緩存行是64個字節寬的處理器,若是隊列的頭節點和尾節點都不足64字節的話,處理器會將他們讀到同一個高速緩存行,修改頭節點時,會將整個緩存行鎖定,致使其它的處理器不能讀到本身的高速緩存區的尾節點。影響出隊列和入隊列操做的效率。追加64字節可以對volatile的性能進行優化,避免頭節點和尾節點同時加載到同一個高速緩存行中,避免互相鎖定。atom
上面的追加字節的方式可能在Java 7 中不生效,它會淘汰或重排序無用的字段,除了volatile,Java中用的較多的的synchronized,下面看一下:spa
synchronized是一種重量級鎖,Java中每一個對象多能夠做爲鎖,具體是下面3種形式:
(1)、普通同步方法,鎖是當前實例對象.net
(2)、靜態同步方法,瑣是當前類的Class對象線程
(3)、同步方法塊,鎖是synchronized 括號裏配置的對象對象
synchronized用的鎖是存在Java對象頭的,對象頭中有字段標示當前是哪一種鎖,鎖一共4種狀態、級別由低到高:無鎖狀態、偏向鎖狀態、輕量級鎖、重量級鎖
三種鎖的對比
鎖 | 優勢 | 缺點 | 適用場景 |
偏向鎖 | 加鎖和解鎖不須要額外的消耗, | 若是線程間存在鎖的競爭,會帶來額外的鎖撤銷的消耗 | 適用於只有一個線程訪問同步塊的場景 |
輕量級鎖 | 競爭的線程不會阻塞,提升了線程的響應時間 | 若是始終得不到鎖競爭的線程,會自旋消耗CPU | 追求響應時間,同步塊執行很是快 |
重量級鎖 | 線程競爭不會使用自旋,不會消耗CPU, | 線程阻塞,響應時間緩慢 | 追求吞吐量,同步塊執行速度較慢 |
原子操做是指不可中斷的一個或一系列的操做,通常的處理器是利用總線加鎖或者緩存加鎖的方式實現多處理器之間的原子操做。
總線鎖定:處理器提供一個LOCK # 信號,剛一個處理器在總線上輸出一個信號時,其它的處理器請求就會被阻塞住,那麼該處理器就能夠獨佔共享內存了。
緩存鎖定:內存區域若是被緩存在處理器的緩存行中,在Lock操做期間被鎖定,在執行鎖操做回寫到內存時,處理器不在總線上聲言LOCK #信號,而是修改內存地址,緩存的一致性機制會阻止同時修改由2個以上處理器緩存的內存區數據,其餘的處理器成功回寫被鎖定的緩存行數據時,會使緩存行無效,其它的處理器就不能在使用這個緩存行了。
Java中是經過使用鎖個CAS(atomic包)的方式來實現原子操做。
參考:http://blog.csdn.net/wusd1256/article/details/78165536