Java高併發之從零到放棄

2021-09-22 17:21:39 字數 2858 閱讀 3275

前言

本篇主要講解如何去優化鎖機制

或者克服多執行緒因為鎖可導致效能下降的問題

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 選擇排...