一、voliatejava
voliate賦予變量在多線程中的可見性,只能做用於變量,非堵塞。java內存模型(以下圖)描述了多線程之間信息交換和同步的方式:每一個線程都從主內存load一份數據到本身的工做內存,線程對變量的讀寫操做都是在工做內存中進行的,而後在save到主內存。bash
若是多線程同時操做主內存贊成拷貝變量a,那麼就可能致使變量的值亂掉,voliate保證了voliate變量值修改後的新值當即同步到主內存,每次使用變量也都從主內存刷新數據,即保證了數據在線程間的可見性以及禁止指令重排序。多線程
二、synchronized異步
synchronize經過加鎖堵塞的方式來實現同步,能夠修飾變量,方法以及代碼塊.性能
Synchronized 的語義底層是經過一個 Monitor 的對象來完成,ui
每一個對象有一個監視器鎖(Monitor),當 Monitor 被佔用時就會處於鎖定狀態。 線程執行 Monitorenter 指令時嘗試獲取 Monitor 的全部權,過程以下: 若是 Monitor 的進入數爲 0,則該線程進入 Monitor,而後將進入數設置爲 1,該線程即爲 Monitor 的全部者。spa
若是線程已經佔有該 Monitor,只是從新進入,則進入 Monitor 的進入數加 1。線程
若是其餘線程已經佔用了 Monitor,則該線程進入阻塞狀態,直到 Monitor 的進入數爲 0,再從新嘗試獲取 Monitor 的全部權。code
執行 Monitorexit 的線程必須是 Objectref 所對應的 Monitor 的全部者。 指令執行時,Monitor 的進入數減 1,若是減 1 後進入數爲 0,那線程退出 Monitor,再也不是這個 Monitor 的全部者orm
三、AtomicInteger
AtomicInteger的本質:自旋鎖+Unsafe的CAS原子操做,非堵塞同步方式(同步指的是一直等待結果,非堵塞是指能夠作其餘的事情,並不釋放cpu資源。)。
網上的一則故事比較生動地講堵塞與同步
故事:老王燒開水。
出場人物:老張,水壺兩把(普通水壺,簡稱水壺;會響的水壺,簡稱響水壺)。
老王想了想,有好幾種等待方式
1.老王用水壺煮水,而且站在那裏,無論水開沒開,每隔必定時間看看水開了沒。-同步阻塞
老王想了想,這種方法不夠聰明。
2.老王仍是用水壺煮水,再也不傻傻的站在那裏看水開,跑去寢室上網,可是仍是會每隔一段時間過來看看水開了沒有,水沒有開就走人。-同步非阻塞
老王想了想,如今的方法聰明瞭些,可是仍是不夠好。
3.老王此次使用高大上的響水壺來煮水,站在那裏,可是不會再每隔一段時間去看水開,而是等水開了,水壺會自動的通知他。-異步阻塞
老王想了想,不會呀,既然水壺能夠通知我,那我爲何還要傻傻的站在那裏等呢,嗯,得換個方法。
4.老王仍是使用響水壺煮水,跑到客廳上網去,等着響水壺本身把水煮熟了之後通知他。-異步非阻塞
老王豁然,這下感受輕鬆了不少。
對於互斥鎖這樣的悲觀鎖,若是資源已經被佔用,資源申請者只能進入睡眠狀態。可是自旋鎖是樂觀鎖,它不會引發調用者睡眠,若是自旋鎖已經被別的執行單元保持,調用者就一直循環在那裏看是否該自旋鎖的保持者已經釋放了鎖,"自旋"一詞就是所以而得名。
複製代碼
優勢:經過CAS保證了原子性
缺點:消耗CPU性能
四、ReentrantLock
重入鎖底層實現是AbstractQueuedSynchronizer,簡稱AQS。synchronized是基於JVM層面實現的,而Lock是基於JDK層面實現的。相比synchronized,ReentrantLock能夠進行鎖的超時和中斷設置。重入性是指若是以獲取鎖的線程再次去獲取鎖,那麼就會獲取鎖成功,獲取鎖成功次數加1,後面釋放鎖鎖的次數必須等於以前成所獲取鎖的的次數,那麼該鎖纔算徹底釋放。
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) { //獲取鎖
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) { //鎖是否被佔用
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) { //佔用鎖的線程是否時當前線程
int nextc = c + acquires; //若是是,則獲取鎖次數+1
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) { //釋放鎖
int c = getState() - releases; //上輩子造的孽,一個個減吧
if (Thread.currentThread() != getExclusiveOwnerThread()) //佔用鎖的線程是否時當前線程
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true; //真正釋放了
setExclusiveOwnerThread(null); //真正釋放了
}
setState(c);
return free;
}
複製代碼