設計一個線程安全的程序尤為重要,尤其是在高并發(fā)環(huán)境下。
對一些的概念進行記錄,如果不對的地方還望指正。
概念
volatile 線程在每次使用變量的時候,都會讀取變量修改后的最的值, 但volatile只能保證可見性,無法保證原子性,所以不能用來做原子性操作。
synchronized Synchronized關鍵字經過編譯后,會在同步塊的前后分別形成monitorenter和monitorexit這兩個字節(jié)碼指令,這兩個字節(jié)碼都需要一個reference類型的參數來指明要鎖定和解鎖的對象。雖然synchronized可以保證在同一時刻,只有同一個線程可以訪問某一方法或者代碼塊,但是鎖機制每次阻塞或喚醒一個線程的時候,都需要操作系統(tǒng)來完成,這里就涉及到系統(tǒng)狀態(tài)轉換的問題(從用戶態(tài)轉換到核心態(tài)),這個過程會耗費CPU很多的時間,成本較大。所以要合理把握鎖的粒度。
CountDownLatch 能夠使一個線程等待其他線程完成各自的工作后再執(zhí)行。他是通過一個計數器來實現(xiàn)的,計數器的初始值為線程的數量。每當一個線程完成了自己的任務后,計數器的值就會減1。當計數器值到達0時,它表示所有的線程已經完成了任務,然后在閉鎖上等待的線程就可以恢復執(zhí)行任務。
*********************************************************************************************************************
線程安全
線程安全實現(xiàn)的方法主要有:非阻塞同步(CAS)、互斥同步、線程局部變量(threadLocal)、wait和notify、java.util.concurrent并發(fā)工具包、volatile保證變量的線程安全等。
CAS:CompareAndSwap,一種保證操作原子性的方法,主要流程是取得i的值(A),進行計算得到(B),去內存中取的值(V),只有A=V 時,才會進行B=A的操作,否則重新取A,直到賦值成功(循環(huán)太多次,對性能有影響)。但這種方法會有一個問題---ABA,即在取A和取V的間隙,對象發(fā)生過改變,java在處理該問題時,提供了一個帶有標記的原子引用類“AtomicStampedReference”,它可以通過控制變量值的版本來保證CAS的正確性。如果要處理ABA問題,互斥同步比原子類更高效。
互斥同步 一般使用synchronized關鍵字實現(xiàn)互斥同步
線程局部變量 每個線程的Thread對象中都有一個ThreadLocalMap對象,這個map存儲了一組以該線程所對應的哈希碼ThreadLocal.threadLocalHashCode為鍵??梢岳斫鉃槊總€使用該變量的線程提供獨立的變量副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。