国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

JavaEE 初階篇-深入了解 CAS 機(jī)制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級(jí)鎖與重量級(jí)鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等)

這篇具有很好參考價(jià)值的文章主要介紹了JavaEE 初階篇-深入了解 CAS 機(jī)制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級(jí)鎖與重量級(jí)鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

??博客主頁(yè):?【小扳_-CSDN博客】
?感謝大家點(diǎn)贊??收藏?評(píng)論?

JavaEE 初階篇-深入了解 CAS 機(jī)制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級(jí)鎖與重量級(jí)鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等),JavaEE 初級(jí)篇,java,開發(fā)語言,java-ee,單例模式,大數(shù)據(jù)

JavaEE 初階篇-深入了解 CAS 機(jī)制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級(jí)鎖與重量級(jí)鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等),JavaEE 初級(jí)篇,java,開發(fā)語言,java-ee,單例模式,大數(shù)據(jù)

文章目錄

? ? ? ? 1.0 樂觀鎖與悲觀鎖概述

? ? ? ? 1.1 悲觀鎖(Pessimistic Locking)

? ? ? ? 1.2 樂觀鎖(Optimistic Locking)

? ? ? ? 1.3 區(qū)別與適用場(chǎng)景

? ? ? ? 2.0 輕量級(jí)鎖與重量級(jí)鎖概述

? ? ? ? 2.1 真正加鎖的底層邏輯順序

? ? ? ? 2.2?輕量級(jí)鎖

? ? ? ? 2.3?重量級(jí)鎖

? ? ? ? 2.4 區(qū)別于適用場(chǎng)景

? ? ? ? 2.5 輕量級(jí)鎖與樂觀鎖的區(qū)別、重量級(jí)鎖與悲觀鎖的區(qū)別

? ? ? ? 3.0 自旋鎖與掛起等待鎖概述

? ? ? ? 3.1 自旋鎖(Spin Lock)

? ? ? ? 3.2 掛起等待鎖(Suspend-Resume Lock)

? ? ? ? 3.3 自旋鎖是一種典型的輕量級(jí)鎖的實(shí)現(xiàn)方式

? ? ? ? 4.0 公平鎖與非公平鎖概述

? ? ? ? 4.1 公平鎖(Fair Lock)

? ? ? ? 4.2 非公平鎖(Unfair Lock)

? ? ? ? 5.0 可重入鎖與不可重入鎖概述

? ? ? ? 6.0 讀寫鎖與互斥鎖概述

? ? ? ? 6.1 讀寫鎖(Read-Write Lock)

? ? ? ? 6.2 互斥鎖(Mutex Lock)

? ? ? ? 7.0 CAS 概述

? ? ? ? 7.1 CAS 的實(shí)際應(yīng)用

? ? ? ? 7.1.1 CAS 的實(shí)際應(yīng)用 - 實(shí)現(xiàn)原子類

? ? ? ? 7.1.2?CAS 的實(shí)際應(yīng)用 - 自旋鎖


? ? ? ? 1.0 樂觀鎖與悲觀鎖概述

????????樂觀鎖和悲觀鎖是兩種并發(fā)控制的策略,用于處理多線程環(huán)境下的數(shù)據(jù)訪問和更新。它們的主要區(qū)別在于對(duì)并發(fā)情況的預(yù)期和處理方式。

? ? ? ? synchronized 是樂觀鎖也悲觀鎖。

JavaEE 初階篇-深入了解 CAS 機(jī)制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級(jí)鎖與重量級(jí)鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等),JavaEE 初級(jí)篇,java,開發(fā)語言,java-ee,單例模式,大數(shù)據(jù)

? ? ? ? 1.1 悲觀鎖(Pessimistic Locking)

? ? ? ? 悲觀鎖的基本思想是在操作數(shù)據(jù)之前先獲取鎖,假定會(huì)并發(fā)訪問,因此在整個(gè)操作過程中都持有鎖,以防其他線程對(duì)數(shù)據(jù)進(jìn)行修改。悲觀鎖通常會(huì)導(dǎo)致其他線程在訪問數(shù)據(jù)時(shí)被阻塞,以確保數(shù)據(jù)的一致性。

? ? ? ? 簡(jiǎn)單來說,在多線程中對(duì)共享變量進(jìn)行操作時(shí),會(huì)認(rèn)為其他線程都會(huì)對(duì)這個(gè)共享變量進(jìn)行操作,因此,從悲觀鎖的角度來說,先加鎖成功后,才能對(duì)共享變量進(jìn)行操作;否則,只能阻塞等待鎖釋放。從而可以確保線程安全。

? ? ? ? 常見的悲觀鎖:synchronized 關(guān)鍵字、ReentrantLock 等鎖機(jī)制。

? ? ? ? 1.2 樂觀鎖(Optimistic Locking)

? ? ? ? 樂觀鎖的基本思想是假設(shè)在數(shù)據(jù)操作過程中不會(huì)發(fā)生并發(fā)沖突,因此不會(huì)立即加鎖,而是在更新數(shù)據(jù)時(shí)檢查是否有其他線程已經(jīng)對(duì)數(shù)據(jù)進(jìn)行修改了。如果沒有發(fā)現(xiàn)數(shù)據(jù)被修改,那么繼續(xù)操作;如果發(fā)現(xiàn)數(shù)據(jù)已經(jīng)被修改了,會(huì)進(jìn)行回滾或者重試。

? ? ? ? 簡(jiǎn)單來說,在多線程中對(duì)共享變量進(jìn)行操作時(shí),一開始不會(huì)認(rèn)為有其他線程會(huì)對(duì)該共享變量進(jìn)行操作,認(rèn)為當(dāng)前線程可以安心的對(duì)該變量進(jìn)行操作。執(zhí)行到后面,如果發(fā)現(xiàn)已經(jīng)有其他線程對(duì)該共享變量進(jìn)行了操作了,那么當(dāng)前的線程執(zhí)行回滾或者重試。

? ? ? ? 1.3 區(qū)別與適用場(chǎng)景

? ? ? ? synchronized 一開始是使用樂觀鎖策略,當(dāng)發(fā)現(xiàn)鎖競(jìng)爭(zhēng)比較頻繁的時(shí)候,就會(huì)自動(dòng)切換悲觀鎖策略。

? ? ? ? 悲觀鎖:真正加上了鎖處理,適用于并發(fā)寫入較多、沖突概率較高的場(chǎng)景,適合長(zhǎng)事務(wù)處理。

? ? ? ? 樂觀鎖:沒有真正的加鎖處理,適用于并發(fā)讀取較多,沖突概率較低的場(chǎng)景,適合短事務(wù)處理。

? ? ? ? 2.0 輕量級(jí)鎖與重量級(jí)鎖概述

????????輕量級(jí)鎖和重量級(jí)鎖是 Java 中用于實(shí)現(xiàn)同步的兩種鎖機(jī)制,用于保護(hù)共享資源在多線程環(huán)境下的訪問。它們的設(shè)計(jì)目的是為了在不同情況下提供更高效的并發(fā)控制。

? ? ? ? synchronized 是輕量級(jí)鎖也是重量級(jí)鎖。

? ? ? ? 2.1 真正加鎖的底層邏輯順序

? ? ? ? CPU 提供了原子操作指令給操作系統(tǒng),操作系統(tǒng)提供了 mutex 互斥鎖給 JVM ,接著 JVM 將鎖封裝成了 synchronized 中的悲觀鎖、ReenTrantLock 等。

? ? ? ? 2.2?輕量級(jí)鎖

? ? ? ? 加鎖機(jī)制盡可能不適用 mutex ,而是盡量在用戶態(tài)代碼中完成,實(shí)在鎖競(jìng)爭(zhēng)太大、鎖沖突太大了,再轉(zhuǎn)換為重量級(jí),即使用 mutex 。

? ? ? ? 輕量級(jí)鎖是一種樂觀鎖機(jī)制,用于優(yōu)先低競(jìng)爭(zhēng)情況下的同步操作。當(dāng)一個(gè)線程嘗試獲取鎖是,如果鎖沒有被其他線程占用,會(huì)將對(duì)象的 Mark Word 指向當(dāng)前線程,將對(duì)象狀態(tài)標(biāo)記為“偏向鎖”。

? ? ? ? 2.3?重量級(jí)鎖

? ? ? ? 加鎖機(jī)制重度依賴了 OS 提供了 mutex ,大量的內(nèi)核態(tài)用戶態(tài)切換,很容易引發(fā)線程的調(diào)度。兩個(gè)操作成本比較高,一旦涉及到用戶態(tài)和內(nèi)核態(tài)的切換,就意味著“滄海桑田”。

? ? ? ? 重量級(jí)鎖是一種悲觀鎖機(jī)制,用于處理高競(jìng)爭(zhēng)情況下的同步操作。當(dāng)多個(gè)線程競(jìng)爭(zhēng)同一把鎖時(shí),會(huì)將鎖升級(jí)為重量級(jí)鎖,線程會(huì)被阻塞,進(jìn)入阻塞狀態(tài)。

? ? ? ? 2.4 區(qū)別于適用場(chǎng)景

? ? ? ? synchronized 開始是一個(gè)輕量級(jí)鎖。如果鎖沖突比較嚴(yán)重,就會(huì)變成重量級(jí)鎖。

????????輕量級(jí)鎖:適用于低競(jìng)爭(zhēng)情況下的同步操作,提高了并發(fā)性能,但在高競(jìng)爭(zhēng)情況下會(huì)升級(jí)為重量級(jí)鎖。

????????重量級(jí)鎖:適用于高競(jìng)爭(zhēng)情況下的同步操作,保證了數(shù)據(jù)的一致性,但在低競(jìng)爭(zhēng)情況下會(huì)帶來額外的開銷。

在實(shí)際應(yīng)用中,Java虛擬機(jī)會(huì)根據(jù)當(dāng)前線程的競(jìng)爭(zhēng)情況動(dòng)態(tài)地選擇輕量級(jí)鎖或重量級(jí)鎖來進(jìn)行同步操作,以提高系統(tǒng)的并發(fā)性能和數(shù)據(jù)一致性。

? ? ? ? 2.5 輕量級(jí)鎖與樂觀鎖的區(qū)別、重量級(jí)鎖與悲觀鎖的區(qū)別

輕量級(jí)鎖:

????????輕量級(jí)鎖是一種樂觀鎖,它嘗試使用 CAS(Compare and Swap)等原子操作來嘗試獲取鎖,避免了線程阻塞和內(nèi)核態(tài)操作,因此被稱為輕量級(jí)。如果 CAS 操作成功,線程就成功獲取了鎖,如果失敗,則會(huì)升級(jí)為重量級(jí)鎖或其他適合的鎖機(jī)制。輕量級(jí)鎖并不是沒有真正的加鎖,而是通過樂觀的方式嘗試獲取鎖,避免了一些開銷較大的操作。

重量級(jí)鎖:

????????重量級(jí)鎖是一種悲觀鎖,它通常會(huì)涉及到線程的阻塞、喚醒和操作系統(tǒng)的調(diào)度等操作,因此被稱為重量級(jí)。當(dāng)多個(gè)線程競(jìng)爭(zhēng)鎖時(shí),重量級(jí)鎖會(huì)導(dǎo)致線程進(jìn)入阻塞狀態(tài),等待其他線程釋放鎖后才能繼續(xù)執(zhí)行。重量級(jí)鎖會(huì)涉及到真正的加鎖操作,包括線程的阻塞和喚醒等。

? ? ? ? 3.0 自旋鎖與掛起等待鎖概述

????????自旋鎖和掛起等待鎖是兩種不同的鎖機(jī)制,它們?cè)谔幚砭€程同步和互斥時(shí)有不同的實(shí)現(xiàn)方式和特點(diǎn)。

? ? ? ? synchronized 是自旋鎖也是掛起鎖。

? ? ? ? 3.1 自旋鎖(Spin Lock)

? ? ? ? 自旋鎖是一種基于忙等待的鎖機(jī)制,當(dāng)一個(gè)線程嘗試獲取鎖時(shí),如果發(fā)現(xiàn)鎖已經(jīng)被其他線程占用,它會(huì)一直循環(huán)檢查鎖的狀態(tài)(自旋)直到鎖可用。自旋鎖適用于鎖被占用時(shí)間較短的情況,因?yàn)樗捎脺p少線程切換的開銷。但是如果鎖被長(zhǎng)時(shí)間占用,自旋鎖會(huì)導(dǎo)致線程長(zhǎng)時(shí)間占用 CPU 資源而無法進(jìn)展,造成性能問題。

? ? ? ? 簡(jiǎn)單來說,自旋鎖一直會(huì)占用 CPU 資源,所謂的“空轉(zhuǎn)”、“忙等待”,只要鎖被釋放了,那么自旋鎖就會(huì)立馬獲取鎖,效率高。

? ? ? ? 按照之前的方式,線程再搶鎖失敗后,進(jìn)入阻塞狀態(tài),放棄 CPU ,需要過很久再次被調(diào)度,但實(shí)際上,大部分情況下,雖然當(dāng)前線程搶鎖失敗,但過不了多久,鎖就會(huì)被釋放。這樣就沒有必要放棄 CPU 資源。這時(shí)候就可以適用自旋鎖來處理這樣的問題。

? ? ? ? 3.2 掛起等待鎖(Suspend-Resume Lock)

? ? ? ? 掛起等待鎖是一種基于線程阻塞和喚醒的鎖機(jī)制,當(dāng)一個(gè)線程嘗試獲取鎖時(shí),如果發(fā)現(xiàn)鎖已經(jīng)被占用,它會(huì)被掛起阻塞等待其他線程釋放鎖。當(dāng)鎖可用時(shí),其他線程會(huì)喚醒被掛起的線程繼續(xù)執(zhí)行。

? ? ? ? 掛起等待鎖適用于鎖被占用時(shí)間長(zhǎng)的情況,因?yàn)樗梢员苊饩€程忙等待占用 CPU 資源,但是會(huì)引入線程切換的開銷。

? ? ? ? 3.3 自旋鎖是一種典型的輕量級(jí)鎖的實(shí)現(xiàn)方式

? ? ? ? synchronized 中的輕量級(jí)鎖策略大概率就是通過自旋鎖的方式實(shí)現(xiàn)的。

優(yōu)點(diǎn):沒有放棄 CPU ,不涉及線程阻塞和調(diào)度,一旦鎖被釋放,就能第一時(shí)間獲取到鎖。

缺點(diǎn):如果鎖被其他線程持有的時(shí)間比較長(zhǎng),那么就會(huì)持續(xù)的消耗 CPU 資源。(而掛起等待的時(shí)候是不會(huì)消耗 CPU 資源的)。

? ? ? ? 相對(duì)應(yīng)的,掛起等待鎖是一種典型的重量級(jí)鎖的實(shí)現(xiàn)方式。

? ? ? ? 4.0 公平鎖與非公平鎖概述

????????公平鎖和非公平鎖是兩種不同的鎖策略,它們主要影響了鎖的獲取順序和公平性。

? ? ? ? synchronized 是非公平鎖。ReenTrantLock 默認(rèn)是非公平鎖,可以轉(zhuǎn)換成公平鎖。

ReentrantLock fairLock = new ReentrantLock(true); // 創(chuàng)建公平鎖

????????通過將參數(shù)設(shè)置為 true,可以創(chuàng)建一個(gè)公平鎖;而默認(rèn)情況下參數(shù)為 false,創(chuàng)建的是非公平鎖。

? ? ? ? 4.1 公平鎖(Fair Lock)

? ? ? ? 公平鎖是一種保證鎖的獲取按照請(qǐng)求的順序進(jìn)行的鎖。當(dāng)一個(gè)線程請(qǐng)求一個(gè)公平鎖時(shí),如果鎖當(dāng)前被其他線程占用,該線程會(huì)進(jìn)入等待隊(duì)列,按照先來先服務(wù)的原則等待獲取鎖。當(dāng)鎖釋放時(shí),等待時(shí)間最長(zhǎng)的線程會(huì)被喚醒并獲取鎖。公平鎖能夠保證線程按照請(qǐng)求的順序獲取鎖,避免了線程饑餓的問題。

? ? ? ? 4.2 非公平鎖(Unfair Lock)

? ? ? ? 非公平鎖是一種允許鎖獲取競(jìng)爭(zhēng)策略,它允許新請(qǐng)求的線程直接嘗試獲取鎖,而不考慮等待隊(duì)列中的線程順序。如果鎖當(dāng)前被其他線程占用,新請(qǐng)求的線程會(huì)直接嘗試獲取鎖,而不會(huì)進(jìn)入等待隊(duì)列。這種策略可能會(huì)導(dǎo)致某些線程長(zhǎng)時(shí)間無法獲取鎖,造成線程饑餓的問題。

? ? ? ? 5.0 可重入鎖與不可重入鎖概述

? ? ? ? 可重入鎖的字面意思是“可以重新進(jìn)入的鎖”,即允許同一個(gè)線程多次獲取同一把鎖。比如一個(gè)遞歸函數(shù)里面加鎖操作,遞歸過程中這個(gè)鎖會(huì)阻塞自己?jiǎn)??如果不?huì),那么這個(gè)鎖就是可重入鎖(因?yàn)檫@個(gè)原因可重入鎖也叫做遞歸鎖)。

? ? ? ? Java 里只要以 ReenTrant 開頭命名的鎖都是可重入鎖,而且 JDK 提供的所有現(xiàn)成的 Lock 實(shí)現(xiàn)類,包括 synchronized 關(guān)鍵字鎖都是可重入鎖。

? ? ? ? 而 Linux 系統(tǒng)提供的 mutex 是不可重入鎖。

? ? ? ? 6.0 讀寫鎖與互斥鎖概述

? ? ? ? 讀寫鎖簡(jiǎn)單來說,讀操作與讀操作并發(fā)執(zhí)行中不會(huì)加鎖,讀操作與寫操作并發(fā)操作中會(huì)加鎖,寫操作與寫操作并發(fā)操作中會(huì)加鎖。

? ? ? ? 互斥鎖簡(jiǎn)單來說,無論進(jìn)行哪一種操作,并發(fā)執(zhí)行的操作都需要加上鎖。

? ? ? ? synchronized 不是讀寫鎖,是互斥鎖。

????????ReenTrantLock 不是讀寫鎖,是互斥鎖。

ReenTrantLock 使用代碼演示:

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private final ReentrantLock lock = new ReentrantLock();
    private int sharedData = 0;

    public void incrementData() {
        lock.lock();
        try {
            sharedData++;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ReentrantLockExample example = new ReentrantLockExample();

        // 創(chuàng)建多個(gè)線程并發(fā)執(zhí)行 incrementData 方法
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                example.incrementData();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                example.incrementData();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final shared data value: " + example.sharedData);
    }
}

? ? ? ? 6.1 讀寫鎖(Read-Write Lock)

? ? ? ? 讀寫鎖允許多個(gè)線程同時(shí)讀取共享資源,但在有寫操作時(shí)需要互斥訪問。

讀操作:

? ? ? ? 多個(gè)線程可以同時(shí)獲取讀鎖,并發(fā)執(zhí)行讀操作,不會(huì)互斥。

寫操作:

? ? ? ? 寫鎖是互斥的,即寫操作與任何其他操作或?qū)懖僮鞫际腔コ獾?。?dāng)有線程持有寫鎖時(shí),其他線程無法獲取讀鎖或者寫鎖,直到寫操作釋放寫鎖。

????????ReentrantReadWriteLock.ReadLock 類表示一個(gè)讀鎖,這個(gè)對(duì)象提供了 lock/unlock 方法進(jìn)行加鎖解鎖。

????????ReentrantReadWriteLock.WriteLock 類表示一個(gè)寫鎖,這個(gè)對(duì)象提供了 lock/unlock 方法進(jìn)行加鎖解鎖。

代碼如下:

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class MyReentrantLock {

    private int data = 100;
    private final ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
    private final ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
    private final ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();
    public int readData(){
        readLock.lock();
        try {
            return data;
        }finally {
            readLock.unlock();
        }
    }

    public void writeData(int data){
        writeLock.lock();
        try {
            this.data = data;
        }finally {
            writeLock.unlock();
        }
    }
}
public class demo1 {
    public static void main(String[] args) {
        MyReentrantLock myReentrantLock = new MyReentrantLock();
        //讀取數(shù)據(jù)
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName() + "-->讀取數(shù)據(jù)為: " + myReentrantLock.readData());
            }).start();

        }

        //寫數(shù)據(jù)
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
               myReentrantLock.writeData(1);
            }).start();
        }

        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName() + "-->讀取數(shù)據(jù)為: " + myReentrantLock.readData());
            }).start();

        }
    }
}

? ? ? ? 6.2 互斥鎖(Mutex Lock)

? ? ? ? 互斥鎖是一種常見的鎖機(jī)制,用于保護(hù)共享資源的互斥訪問。無論是讀操作還是寫操作,都要獲取互斥鎖才能訪問共享資源。

? ? ? ? 7.0 CAS 概述

????????CAS(Compare and Swap)是一種并發(fā)控制機(jī)制,通常用于實(shí)現(xiàn)無鎖算法。它主要用于解決多線程并發(fā)訪問共享數(shù)據(jù)時(shí)的原子性操作問題。

????????CAS 的基本原理是利用 CPU 提供的原子性指令來實(shí)現(xiàn)無鎖的原子操作。當(dāng)多個(gè)線程同時(shí)嘗試執(zhí)行 CAS 操作時(shí),只有一個(gè)線程會(huì)成功,其他線程會(huì)失敗并重試。

CAS 操作包括三個(gè)步驟:

? ? ? ? 1)比較(Compare):首先, CAS 會(huì)比較當(dāng)前內(nèi)存中的值和預(yù)期值是否相等。

? ? ? ? 2)交換(Swap):如果相等,CAS 就會(huì)將新值寫入到主內(nèi)存中;否則,不做任何操作。

? ? ? ? 3)返回(Return):CAS 操作會(huì)返回操作是否成功的結(jié)果,通常時(shí)一個(gè)布爾值。

? ? ? ? 這三個(gè)操作都是原子性的,因此不存在線程安全問題。

圖解:

JavaEE 初階篇-深入了解 CAS 機(jī)制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級(jí)鎖與重量級(jí)鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等),JavaEE 初級(jí)篇,java,開發(fā)語言,java-ee,單例模式,大數(shù)據(jù)

? ? ? ? 7.1 CAS 的實(shí)際應(yīng)用

? ? ? ? 原子操作、非阻塞算法、自旋鎖、ABA 問題的解決、樂觀鎖的實(shí)現(xiàn)等。

? ? ? ? 7.1.1 CAS 的實(shí)際應(yīng)用 - 實(shí)現(xiàn)原子類

????????CAS 可以用于實(shí)現(xiàn)原子操作,比如 AtomicInteger、AtomicLong 等原子類都是基于 CAS 實(shí)現(xiàn)的。在多線程環(huán)境下,通過 CAS 可以確保對(duì)共享變量的操作是原子的,避免了使用鎖帶來的性能開銷。

? ? ? ? 比如說 AtomicInteger 類,是基于 CAS 的思想實(shí)現(xiàn)的,假如有一個(gè) AtomicInteger 的實(shí)例對(duì)象,在多線程中,對(duì)該實(shí)例對(duì)象進(jìn)行 +1 操作,一般來說,如果不加鎖的話,會(huì)出現(xiàn)線程安全問題,但是對(duì)于當(dāng)前對(duì)象來說,即使不用加鎖,也不用出現(xiàn)線程安全問題。

代碼如下:

import java.util.concurrent.atomic.AtomicInteger;

public class MyAtomicInteger {
    private AtomicInteger count = new AtomicInteger(0);

    public void add(){
        System.out.println(count.incrementAndGet());
    }
}
public class Text {
    public static void main(String[] args) {
        MyAtomicInteger myAtomicInteger = new MyAtomicInteger();
        for (int i = 0; i < 1000; i++) {
            new Thread(()->{
                for (int j = 0; j < 5000; j++) {
                    myAtomicInteger.add();
                }
            }).start();
        }
    }
}

運(yùn)行結(jié)果如下:

JavaEE 初階篇-深入了解 CAS 機(jī)制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級(jí)鎖與重量級(jí)鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等),JavaEE 初級(jí)篇,java,開發(fā)語言,java-ee,單例模式,大數(shù)據(jù)

? ? ? ? 運(yùn)行結(jié)果是正確的,沒有出現(xiàn)線程安全問題。

? ? ? ? 這是為什么即使沒有加上鎖也不會(huì)出現(xiàn)線程安全問題呢?

? ? ? ? 答案就在用了 AtomicInteger 修飾的變量,且 +1 操作用到了 count.incrementAndGet() 實(shí)例方法。

詳細(xì)對(duì)?count.incrementAndGet() 方法進(jìn)行分析:

JavaEE 初階篇-深入了解 CAS 機(jī)制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級(jí)鎖與重量級(jí)鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等),JavaEE 初級(jí)篇,java,開發(fā)語言,java-ee,單例模式,大數(shù)據(jù)

? ? ? ? 該方法中還包含了 getAndAddInt() 方法,第一個(gè)參數(shù)是代表著當(dāng)前對(duì)象,第二個(gè)參數(shù)可以認(rèn)為是存放值的地址,第三個(gè)參數(shù)默認(rèn)為 1 。

進(jìn)入 getAndAddInt() 方法進(jìn)行分析:

JavaEE 初階篇-深入了解 CAS 機(jī)制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級(jí)鎖與重量級(jí)鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等),JavaEE 初級(jí)篇,java,開發(fā)語言,java-ee,單例模式,大數(shù)據(jù)

? ? ? ? ?參數(shù) o 代表著當(dāng)前對(duì)象,參數(shù) offset 代表著值的地址,參數(shù) delta 為 1 。該方法中內(nèi)部定義了一個(gè)變量 v ,通過 getIntVolatile() 這個(gè)方法,用當(dāng)前的對(duì)象還有值的地址獲取到最新的數(shù)據(jù)賦值給 v 。再接著通過 weakCompareAndSetInt() 方法,來比較當(dāng)前的 v 跟之前獲取的 v 的值是否相同,如果相同,代表著沒有線程訪問這個(gè)數(shù)據(jù),只有當(dāng)前線程正在訪問,那么就可以對(duì)這個(gè)數(shù)據(jù)進(jìn)行修改,再返回到主內(nèi)存中;如果不相同,代表有其他線程訪問這個(gè)數(shù)據(jù),此時(shí)不能直接將當(dāng)前線程更新的值放到主內(nèi)存中,會(huì)出現(xiàn)線程安全問題,因此重復(fù)循環(huán),再來新一輪,先獲取主內(nèi)存中最新的數(shù)據(jù),在來比較當(dāng)前數(shù)據(jù)與之前獲取到的 v 是否相同...一直循環(huán)往復(fù)。直到當(dāng)前數(shù)據(jù)與之前的獲取到的 v 相同,那么就可以將值放入到內(nèi)存中。

進(jìn)入 weakCompareAndSetInt() 方法進(jìn)行分析:

JavaEE 初階篇-深入了解 CAS 機(jī)制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級(jí)鎖與重量級(jí)鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等),JavaEE 初級(jí)篇,java,開發(fā)語言,java-ee,單例模式,大數(shù)據(jù)

? ? ? ? 如果成功就返回 true,否則返回 false 。?

? ? ? ? 最后,可以清楚的了解到以上這個(gè)思想跟 CAS 的機(jī)制是一致的。

? ? ? ? 7.1.2?CAS 的實(shí)際應(yīng)用 - 自旋鎖

? ? ? ? 自旋鎖是基于 CAS 機(jī)制實(shí)現(xiàn)更靈活的鎖,獲取到更多的控制權(quán)。

偽代碼:

public class MySpinLock {
    private  Thread ower = null;

    public void lock(){
        //通過 CAS 看當(dāng)前鎖是否被某個(gè)線程持有
        //如果這個(gè)鎖已經(jīng)被別的線程持有,那么就自旋等待。
        //如果這個(gè)鎖沒有被別的線程持有,那么就把 ower 設(shè)為當(dāng)前嘗試加鎖的線程。
        while (!CAS(this.ower,null,Thread.currentThread())){

        }
    }

    public void unlock(){
        this.ower = null;
    }
}

? ? ? ? 結(jié)合自旋鎖的特點(diǎn)和 CAS 機(jī)制來分析,線程只要沒有獲取的鎖,就會(huì)一直占用 CPU 資源等待,直到鎖釋放為止,如何來判斷鎖是否被占用呢?

? ? ? ? 就可以通過 CAS 機(jī)制來判斷,大概流程是:判斷當(dāng)前的線程 ower 是否為 null ,如果是,則將 ower 修改為當(dāng)前線程所持有,這樣來看,其他線程也會(huì)通過 CAS 機(jī)制來判斷當(dāng)前的 ower 是否否為 null ,返回結(jié)果為 false ,則只能空轉(zhuǎn)了,等待當(dāng)前線程釋放鎖,此時(shí)釋放鎖會(huì)把 ower 賦值為 null 。交給其他線程來獲取這把“鎖”。?

JavaEE 初階篇-深入了解 CAS 機(jī)制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級(jí)鎖與重量級(jí)鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等),JavaEE 初級(jí)篇,java,開發(fā)語言,java-ee,單例模式,大數(shù)據(jù)文章來源地址http://www.zghlxwxcb.cn/news/detail-853034.html

到了這里,關(guān)于JavaEE 初階篇-深入了解 CAS 機(jī)制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級(jí)鎖與重量級(jí)鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實(shí)現(xiàn) TCP 通信群聊)

    JavaEE 初階篇-深入了解 UDP 通信與 TCP 通信(綜合案例:實(shí)現(xiàn) TCP 通信群聊)

    ??博客主頁(yè):?【 小扳_-CSDN博客】 ?感謝大家點(diǎn)贊??收藏?評(píng)論? 文章目錄 ? ? ? ? 1.0 UDP 通信 ????????1.1 DatagramSocket 類 ????????1.2 DatagramPacket 類 ????????1.3 實(shí)現(xiàn) UDP 通信(一發(fā)一收) ? ? ? ? 1.3.1 客戶端的開發(fā) ? ? ? ? 1.3.2 服務(wù)端的開發(fā) ????????1.4 實(shí)

    2024年04月26日
    瀏覽(21)
  • JavaEE 初階篇-深入了解 I/O 高級(jí)流(緩沖流、交換流、數(shù)據(jù)流和序列化流)

    JavaEE 初階篇-深入了解 I/O 高級(jí)流(緩沖流、交換流、數(shù)據(jù)流和序列化流)

    ??博客主頁(yè):?【 小扳_-CSDN博客】 ?感謝大家點(diǎn)贊??收藏?評(píng)論? 文章目錄 ? ? ? ? 1.0 緩沖流概述 ? ? ? ? 1.1 緩沖流的工作原理 ? ? ? ? 1.2 使用緩沖流的步驟 ? ? ? ? 1.3?字節(jié)緩沖流于字符緩沖流的區(qū)別 ? ? ? ? 1.4?字節(jié)緩沖流的實(shí)例 ? ? ? ? 1.5?字符緩沖流的實(shí)例

    2024年04月29日
    瀏覽(20)
  • JavaEE 初階篇-生產(chǎn)者與消費(fèi)者模型(線程通信)

    JavaEE 初階篇-生產(chǎn)者與消費(fèi)者模型(線程通信)

    ??博客主頁(yè):?【 小扳_-CSDN博客】 ?感謝大家點(diǎn)贊??收藏?評(píng)論? ? 文章目錄 ? ? ? ? 1.0 生產(chǎn)者與消費(fèi)者模型概述 ? ? ? ? 2.0?在生產(chǎn)者與消費(fèi)者模型中涉及的關(guān)鍵概念 ? ? ? ? 2.1 緩沖區(qū) ? ? ? ? 2.2 生產(chǎn)者 ? ? ? ? 2.3 消費(fèi)者 ? ? ? ? 2.4 同步機(jī)制 ? ? ? ? 2.5 線程間通

    2024年04月28日
    瀏覽(31)
  • 【JavaEE初階】多線程進(jìn)階(五)常見鎖策略 CAS synchronized優(yōu)化原理

    【JavaEE初階】多線程進(jìn)階(五)常見鎖策略 CAS synchronized優(yōu)化原理

    樂觀鎖:預(yù)測(cè)鎖競(jìng)爭(zhēng)不是很激烈。 悲觀鎖:預(yù)測(cè)鎖競(jìng)爭(zhēng)會(huì)很激烈。 以上定義并不是絕對(duì)的,具體看預(yù)測(cè)鎖競(jìng)爭(zhēng)激烈程度的結(jié)論。 輕量級(jí)鎖加鎖解鎖開銷比較小,效率更高。 重量級(jí)鎖加鎖解鎖開銷比較大,效率更低。 多數(shù)情況下,樂觀鎖也是一個(gè)輕量級(jí)鎖。 多數(shù)情況下,悲

    2024年02月03日
    瀏覽(31)
  • JavaEE 初階篇-線程安全的集合類、多線程環(huán)境使用 ArrayList、隊(duì)列、哈希表(HashMap 、ConCurrentHashMap 、HashTable 的區(qū)別)

    JavaEE 初階篇-線程安全的集合類、多線程環(huán)境使用 ArrayList、隊(duì)列、哈希表(HashMap 、ConCurrentHashMap 、HashTable 的區(qū)別)

    ??博客主頁(yè):?【 小扳_-CSDN博客】 ?感謝大家點(diǎn)贊??收藏?評(píng)論? ? 文章目錄 ? ? ? ? 1.0 線程安全的集合類 ? ? ? ? 1.2?線程安全的集合類 - Vector ? ? ? ? 1.3 線程安全的集合類 - Stack ? ? ? ? 1.4 線程安全的集合類 - HashTable ? ? ? ? 2.0 多線程環(huán)境使用 ArrayList ? ? ? ?

    2024年04月25日
    瀏覽(59)
  • 【JavaEE初階】了解JVM

    【JavaEE初階】了解JVM

    JVM啟動(dòng)的時(shí)候,會(huì)申請(qǐng)到一整個(gè)很大的內(nèi)存區(qū)域.JVM是一個(gè)應(yīng)用程序,要從操作系統(tǒng)里申請(qǐng)內(nèi)存.JVM就根據(jù)需要,把空間分為幾個(gè)部分,每個(gè)部分各自有不同的功能.具體劃分如下: Native Method Stacks(本地方法棧) :native表示是JVM內(nèi)部的C++代碼.就是給調(diào)用native方法(JVM內(nèi)部的方法)準(zhǔn)備的???/p>

    2024年02月13日
    瀏覽(25)
  • 了解JVM(JavaEE初階系列19)

    了解JVM(JavaEE初階系列19)

    目錄 前言: 1.JVM是如何運(yùn)行的 2.JVM中的內(nèi)存區(qū)域劃分 3.JVM的類加載機(jī)制 3.1JVM加載機(jī)制的五大步驟 3.1.1加載 3.1.1驗(yàn)證 3.1.1準(zhǔn)備 3.1.1解析 3.1.1初始化 3.2總結(jié) 3.3JVM啟動(dòng)時(shí)機(jī) 3.4雙親委派模型 4.JVM中的垃圾回收策略 4.1JVM垃圾回收機(jī)制概念 4.2垃圾回收策略 4.2.1判斷引用是否有指向 4

    2024年02月10日
    瀏覽(39)
  • 亞信安慧AntDB:深入了解AntDB-M元數(shù)據(jù)鎖的實(shí)現(xiàn)之相關(guān)概念

    亞信安慧AntDB:深入了解AntDB-M元數(shù)據(jù)鎖的實(shí)現(xiàn)之相關(guān)概念

    AntDB-M在架構(gòu)上分為兩層,服務(wù)層和存儲(chǔ)引擎層。元數(shù)據(jù)的并發(fā)管理集中在服務(wù)層,數(shù)據(jù)的存儲(chǔ)訪問在存儲(chǔ)引擎層。為了保證DDL操作與DML操作之間的一致性,引入了元數(shù)據(jù)鎖(MDL)。AntDB-M提供了豐富的元數(shù)據(jù)鎖功能,然而高并發(fā)鎖操作很容易出現(xiàn)鎖競(jìng)爭(zhēng)、等待、死鎖的問題,

    2024年01月22日
    瀏覽(23)
  • 每天40min,我們一起用70天穩(wěn)扎穩(wěn)打?qū)W完《JavaEE初階》——12/70 第十二天【線程池 面試題】

    專注 效率 記憶 預(yù)習(xí) 筆記 復(fù)習(xí) 做題 歡迎觀看我的博客,如有問題交流,歡迎評(píng)論區(qū)留言,一定盡快回復(fù)?。ù蠹铱梢匀タ次业膶?,是所有文章的目錄) 文章字體風(fēng)格: 紅色文字表示:重難點(diǎn)★? 藍(lán)色文字表示:思路以及想法★? 如果大家覺得有幫助的話,感謝大家?guī)?/p>

    2024年02月13日
    瀏覽(29)
  • 學(xué)習(xí)JavaEE的日子 day13補(bǔ) 深入類加載機(jī)制及底層

    學(xué)習(xí)JavaEE的日子 day13補(bǔ) 深入類加載機(jī)制及底層

    初識(shí)類加載過程 使用某個(gè)類時(shí),如果該類的class文件沒有加載到內(nèi)存時(shí),則系統(tǒng)會(huì)通過以下三個(gè)步驟來對(duì)該類進(jìn)行初始化 1.類的加載(Load) → 2.類的連接(Link) → 3.類的初始化(Initialize) 類的加載(Load):將類的class文件讀入內(nèi)存,并為之創(chuàng)建一個(gè)java.lang.Class的對(duì)象,此

    2024年01月18日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包