(轉(zhuǎn)載)Java CAS 和 synchronized 和 Lock

原文鏈接:Java CAS 和 synchronized 和 Lock - CSDN博客

CAS 機(jī)制

適用場(chǎng)景:樂觀認(rèn)為并發(fā)不高,不需要阻塞,可以不上鎖。?

特點(diǎn):不斷比較更新,直到成功。

缺點(diǎn):高并發(fā)cpu壓力大;ABA問題。

ABA問題:?

CAS機(jī)制生效的前提是,取出內(nèi)存中某時(shí)刻的數(shù)據(jù),而在下時(shí)刻比較并替換。?

如果在比較之前,數(shù)據(jù)發(fā)生了變化,例如:A->B->A,即A變?yōu)锽然后又變化A,那么這個(gè)數(shù)據(jù)還是發(fā)生了變化,但是CAS還是會(huì)成功。

Java中CAS機(jī)制使用版本號(hào)進(jìn)行對(duì)比,避免ABA問題。

synchronized

適用場(chǎng)景:悲觀認(rèn)為并發(fā)很高,需要阻塞,需要上鎖。

特點(diǎn):語言層面的優(yōu)化,鎖粗化、偏向鎖、輕量鎖等等;可讀性高。

ReentrantLock 和 Atomic類

以上兩種并發(fā)工具都使用了CAS機(jī)制。?

在并發(fā)不高競(jìng)爭(zhēng)不激烈時(shí)候,性能略低于synchronized;相反,并發(fā)高競(jìng)爭(zhēng)激烈時(shí)候,性能高于synchronized。

ReentrantLock相對(duì)于synchronized:

ReentrantLock等待可中斷,synchronized不可以。

ReentrantLock需要手動(dòng)釋放鎖,synchronized不需要。

ReentrantLock可支持公平非公平鎖,synchronized只支持非公平鎖。

ReentrantLock沒有語言層面的優(yōu)化,底層實(shí)現(xiàn)機(jī)制AQS和CAS,synchronized有優(yōu)化。

ReentrantLock可重入鎖,synchronized不可重入,可能導(dǎo)致死鎖。

ReentrantLock支持讀寫鎖,可以提高高并發(fā)讀操作。

synchronized由操作系統(tǒng)支持,涉及內(nèi)核態(tài)和用戶態(tài)的上下文切換,并發(fā)高時(shí)切換開銷非常大。

ReentrantLock(AQS)依賴volatile int變量標(biāo)示鎖狀態(tài),結(jié)構(gòu)為雙向鏈表的等待隊(duì)列,通過(cas+死循環(huán))更改鎖狀態(tài),一旦更新成功,標(biāo)示競(jìng)爭(zhēng)到鎖。

AQS釋放鎖:?

通過cas改變狀態(tài)

private void doReleaseShared() {

? ? ? ? /*

? ? ? ? * Ensure that a release propagates, even if there are other

? ? ? ? * in-progress acquires/releases.? This proceeds in the usual

? ? ? ? * way of trying to unparkSuccessor of head if it needs

? ? ? ? * signal. But if it does not, status is set to PROPAGATE to

? ? ? ? * ensure that upon release, propagation continues.

? ? ? ? * Additionally, we must loop in case a new node is added

? ? ? ? * while we are doing this. Also, unlike other uses of? ? ? ? * unparkSuccessor, we need to know if CAS to reset status

? ? ? ? * fails, if so rechecking.

? ? ? ? */

? ? ? ? for (;;) {

? ? ? ? ? ? Node h = head;

? ? ? ? ? ? if (h != null && h != tail) {

? ? ? ? ? ? ? ? int ws = h.waitStatus;

? ? ? ? ? ? ? ? if (ws == Node.SIGNAL) {

? ? ? ? ? ? ? ? ? ? if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))

? ? ? ? ? ? ? ? ? ? ? ? continue;? ? ? ? ? ? // loop to recheck cases

? ? ? ? ? ? ? ? ? ? unparkSuccessor(h);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? else if (ws == 0 &&

? ? ? ? ? ? ? ? ? ? ? ? !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))

? ? ? ? ? ? ? ? ? ? continue;? ? ? ? ? ? ? ? // loop on failed CAS

? ? ? ? ? ? }

? ? ? ? ? ? if (h == head)? ? ? ? ? ? ? ? ? // loop if head changed

? ? ? ? ? ? ? ? break;

? ? ? ? }

? ? }

獲取鎖:?

如果獲取到鎖,設(shè)為頭節(jié)點(diǎn),否則一直自旋等待,在高并發(fā)時(shí),可以避免大量鎖競(jìng)爭(zhēng)的上下文切換,降低線程切換開銷。

private void doAcquireInterruptibly(int arg)

? ? ? ? throws InterruptedException {

? ? ? ? final Node node = addWaiter(Node.EXCLUSIVE);

? ? ? ? boolean failed = true;

? ? ? ? try {

? ? ? ? ? ? for (;;) {

? ? ? ? ? ? ? ? final Node p = node.predecessor();

? ? ? ? ? ? ? ? if (p == head && tryAcquire(arg)) {

? ? ? ? ? ? ? ? ? ? setHead(node);

? ? ? ? ? ? ? ? ? ? p.next = null; // help GC? ? ? ? ? ? ? ? ? ? failed = false;

? ? ? ? ? ? ? ? ? ? return;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? if (shouldParkAfterFailedAcquire(p, node) &&

? ? ? ? ? ? ? ? ? ? parkAndCheckInterrupt())

? ? ? ? ? ? ? ? ? ? throw new InterruptedException();

? ? ? ? ? ? }

? ? ? ? } finally {

? ? ? ? ? ? if (failed)

? ? ? ? ? ? ? ? cancelAcquire(node);

? ? ? ? }

? ? }

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容