- 1.volatile不具備原子性
- 2.volatile不具備互斥性(不能保證數據始終只有一個線程訪問,同步代碼塊可以保證)
- volatile保證內存可見性,每個線程有單獨的一塊緩存,造成共享數據的不同步,volatile修飾關鍵字可以保證直接操作主存中的數據
atomic包裝類:
/*
* 一、i++ 的原子性問題:i++ 的操作實際上分爲三個步驟“讀-改-寫”
* int i = 10;
* i = i++; //10
*
* int temp = i;
* i = i + 1;
* i = temp;
*
* 二、原子變量:在 java.util.concurrent.atomic 包下提供了一些原子變量。
* 1. volatile 保證內存可見性
* 2. CAS(Compare-And-Swap) 算法保證數據變量的原子性
* CAS 算法是硬件對於併發操作的支持
* CAS 包含了三個操作數:
* ①內存值 V
* ②預估值 A
* ③更新值 B
* 當且僅當 V == A 時, V = B; 否則,不會執行任何操作。
*/
atomic包裝類:
- 內部使用volatile修飾保證內存可見性
- CAS(Compare - And - Swap)算法整整數據原子性
常用同步集合類
- 可以對List進行同步包裝,使用Collctions.synchoronizedlist();其實是把內部每個方法變爲同步方法
- copyOnWriteArrayList-Set適合併發迭代讀取,效率由於同步ArrayList,JDK1.8後ConcurrentHashMap內部實現機制由“分段鎖”變爲CAS算法實現
- 在解決List迭代+添加數據時,同步ArrayList會出現同步修改異常,可以使用copyOnwriteArrayList進行處理:原理是:add時會複製新列表進行添加,不會出現線程操作問題
CountDownLatch閉鎖
等待一系列流程執行完後閉鎖繼續進行後續流程,而不是直接結束主線程
實現多線程的第三種方式:
* 創建執行線程的方式三:實現Callable接口,相較於Runnable接口,方法可以返回值,並且可以拋出異常
* 執行Callable方法需要FutureTask實現類的支持,用於接收運算結果,FutrueTask是Futrue實現類,其實也是使用閉鎖計算完成後進行回調處理
解決線程安全問題的三種方式:
- 同步代碼塊
- 同步方法
- JDK1.5以後同步鎖