鎖原理分析 併發構件

2021-08-18 10:10:01 字數 2851 閱讀 7752

1.併發構件

構件備註

synchronize

jvm層實現

synchronize(object)
synchronize(this)
synchronize(object.class)
推薦使用第一種,後兩者直接鎖住類效率低

reentrantlock

**層實現的鎖

class reentrantlock

class fairsync extends sync

class nonfairsync extends sync

}

使用方法:一般情況下lock與unlock配對使用,必須在lock之後釋放資源(unlock)

reetrantlock lock = new reetrantlock();

lock.lock();

// do

lock.unlock();

預設構造器new的是nonfairsync例項,帶int引數的構造器new的是fairsync例項

countdownlatch

countdownlatch latch = new countdownlatch(num);

latch.countdown(); //count--

latch.await();  //等待count為0

cyclicbarrier

cyclicbarrier barrier = new cyclicbarrier( num, new runnable(){});

barrier.await(); //count-- 計數器為0時執行runnable中的語句

與countdownlatch類似

以上併發構件底層均依賴 abctractqueuedsynchronizer實現;

2. abctractqueuedsynchronizer(aqs)原理,原始碼解析

class abstractqueuedsynchronizer extends abstractownablesynchronizer

public class conditionobject{}

}

node是aqs的fifo佇列的成員,node內部字段如下:

waitstatus

volatile int

當前狀態

signal    = -1 :後繼執行緒需要喚醒

cancelled =  1 :當前執行緒取消

condition = -2 :某條件下等待

propagate = -3 :後繼是共享模式

prev

volatile node

前驅結點

next

volatile node

後繼節點

thread

volatile thread

當前執行緒

nextwaiter

node

原子操作方法:

compareandsetstate(int,int)

設定鎖狀態

compareandsethead(node)

aqs佇列頭

compareandsettail(node)

aqs佇列尾

compareandsetnext(node,node,node)

設定佇列中結點的後繼

compareandsetwaitstatus(node,int,int)

設定結點的等待狀態

(1)獲取鎖:

addwaiter : 將當前執行緒新增到aqs佇列尾部,若tail不為null則快速入隊,否則enq(node);enq時若tail為空,則先初始化tail,再將當前結點新增到隊尾;for迴圈保證當前結點能夠成功新增進隊尾;

acquirequeued:自旋鎖,當前執行緒自旋等待,直到前驅結點是頭頭結點且當前結點獲取到鎖(state),當前結點為頭結點,自旋等待結束;

public final void acquire(int arg)
private node addwaiter(node mode) 

}enq(node);

return node;

}

private node enq(final node node)  else }}

}

final boolean acquirequeued(final node node, int arg) 

if (shouldparkafte***iledacquire(p, node) &&

parkandcheckinterrupt())

interrupted = true;

}} finally

}

(2)釋放鎖:

只有頭結點可以釋放鎖,且佇列中每個結點只能由自己的前驅結點喚醒;

若頭結點等待狀態小於0,則將等待狀態設定為0,若後繼結點為空,則從隊尾開始尋找乙個等待的結點,喚醒後繼結點;

public final boolean release(int arg) 

return false;

}private void unparksuccessor(node node)

if (s != null)

locksupport.unpark(s.thread);

}

java併發 CAS原理學習 樂觀鎖 悲觀鎖

在之前文章中驗證了在多執行緒場景下,cas可以保證共享變數的原子性。此篇文章主要記錄一下cas原理的學習感悟。在一般情況下,為保證資料安全性,我們可以採用synchronized修飾變數或者修飾方法。也就是說在同一時間只有乙個執行緒能修改共享變數或者訪問這個方法,其它執行緒都要等待。但是這樣的話,也...

Java併發編 Java鎖的實現原理

多cpu 一台計算機上多個物理cpu 多核 乙個cpu上多個核心 超執行緒技術 乙個核心多個執行執行單元 高度快取l1 l2 l3 4核8執行緒 這樣就存在快取一致性問題。解決快取一致性問題的方法 匯流排鎖和快取鎖 1 匯流排鎖 這樣之後i的值都為2,但是我們期待的結果是i 3。那麼匯流排鎖的意思是...

mysql 併發 鎖表 mysql 併發插入鎖表

執行過程如下 set autocommit 0 session a insert into bpm pro status values 1 1 usertask1 使用者任務1 1 2015 11 12 00 00 00 test1 1 10000000490026 0 結果 sql insert ...