前言
本篇主要講解如何去優化鎖機制
或者克服多執行緒因為鎖可導致效能下降的問題
threadlocal執行緒變數
有這樣乙個場景,前面是一大桶水,10個人去喝水,為了保證執行緒安全,我們要在杯子上加鎖
導致大家輪著排隊喝水,因為加了鎖的杯子是同步的,只能有乙個人拿著這個唯一的杯子喝水
這樣子大家都喝完一杯水需要很長的時間
如果我們給每個人分發乙個杯子呢?是不是每人喝到水的時間縮小到了十分之一
多執行緒併發也是乙個道理
在每個thread中都有自己的資料存放空間(threadlocalmap)
而threadlocal就是在當前執行緒的存放空間中存放資料
下面這個例子,在每個執行緒中存放乙個arraylist,而不是大家去公用乙個arraylist
public class threadlocaltest
@override
public void run()
}public static void main(string args) throws interruptedexception
thread.sleep(3000);
system.out.println(list.size());
es.shutdown();}}
在每個執行緒內部有一塊儲存區域叫做threadlocalmap
可以看到,threadlocal採用set,get訪問值方式
只有執行緒完全關閉時,在threadlocalmap中的資料才會被gc**
這時有乙個值得考慮的問題
我們使用執行緒池來開發的時候,執行緒池中的執行緒並不會關閉,它只是處於空閒狀態
也就是說,我們如果把過大的資料儲存在當前執行緒的threadlocalmap中,執行緒不斷的呼叫,被空閒...
最後會導致記憶體溢位
解決方法是當不需要這些資料時
使用threadlocal.remove()方法將變數給移除
cas操作
還有一種脫離鎖的機制,那就是cas
cas帶著三個變數,分別是:
v更新變數:需要返回的變數
e預期值:原來的值
n新值,傳進來的新變數
只有當預期值和新值相等時,才會把v=n,如果不相等,說明該操作會讓資料無法同步
根據上面的解釋,大概就能知道cas其實也是在保護資料的同步性
當多個執行緒進行cas操作時,可想只有乙個執行緒能成功更新,之後其它執行緒的e和v會不地進行斷比較
所以cas的同步鎖的實現是一樣的
cas操作的並發包在atomic包中,atomic實現了很多態別
不管是atomicinteger還是atomicreference,都有相同點,請觀察它們的原始碼:
private volatile v value;
private static final long valueoffset;
以上是atomicreferenc
private volatile int value;
private static final long valueoffset;
以上是atomicintege
都有value,這是它們的當前實際值
valueoffset儲存的是value的偏移量
下面給出乙個簡單的atomicintege例子:
public class atomictest }}
public static void main(string args) throws interruptedexception
thread.sleep(5000);
system.out.println(atomicinteger);}}
你試著執行一下,如果列印出10000說明執行緒安全
使用cas操作比同步鎖擁有更好的效能
我們來看下incrementandget()的原始碼:
public final int incrementandget()
來看下getandaddint()原始碼:
public final int getandaddint(object var1, long var2, int var4) while(!this.compareandswapint(var1, var2, var5, var5 + var4));
return var5;
}
這裡有乙個迴圈,再細看原始碼發現是native的,雖然看不到原生**,但是可以看出它這裡做了乙個cas操作,不斷地進行多個變數的比較,只有預設值和新值相等時,才跳出迴圈
var5就是需要更新的變數,var1和var2是預設值和新值
死鎖講了那麼多無鎖的操作,我們來看一下乙個死鎖的現象
兩個執行緒互相佔著對方想得到的鎖,就會出現死鎖狀況
public class deadlock extends thread
@override
public void run()}}
if (suo==you)}}
}public static void main(string args) throws interruptedexception
thread.sleep(50000);}}
如圖:
出現了兩個執行緒的死鎖現象,所以說去鎖不僅能提公升效能,也能防止死鎖的產生。
更多參考內容請登入:
Java高併發之從零到放棄
本篇主要講解如何去優化鎖機制 或者克服多執行緒因為鎖可導致效能下降的問題 有這樣乙個場景,前面是一大桶水,10個人去喝水,為了保證執行緒安全,我們要在杯子上加鎖 導致大家輪著排隊喝水,因為加了鎖的杯子是同步的,只能有乙個人拿著這個唯一的杯子喝水 這樣子大家都喝完一杯水需要很長的時間 如果我們給每個人...
從零react從入門到放棄
簡介 react是facebook出的一款針對view視層圖的library 庫 主要使用單向資料流的方式進行資料展示。react擁有較高的效能,邏輯非常簡單,越來越多的人已經開始關注和使用他 src script src script src script 通過npm或yarn使用react 國內...
演算法之從入門到放棄
該系列筆記意在學習總結資料結構和演算法相關知識點 分享競賽和考研 工作面試中涉及的題目。該系列文章不定期更新,預計在2021 06 01前全部完成。以下是相關鏈結。如有錯誤,歡迎指正。1 基礎演算法 1.1 列舉 遍歷 1.2 模擬 1.3 遞迴 分治 1.4 貪心 1.5 排序 1.5.1 選擇排...