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

《微服務(wù)實(shí)戰(zhàn)》 第二十六章 Java鎖的分類

這篇具有很好參考價(jià)值的文章主要介紹了《微服務(wù)實(shí)戰(zhàn)》 第二十六章 Java鎖的分類。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

系列文章目錄

第二十八章 分布式鎖框架-Redisson
第二十七章 CAS
第二十六章 Java鎖的分類
第二十五章 Java多線程安全與鎖
第二章 CountDownLatch和Semaphone的應(yīng)用
第一章 Java線程池技術(shù)應(yīng)用

《微服務(wù)實(shí)戰(zhàn)》 第二十六章 Java鎖的分類



前言

本章節(jié)介紹Java中的幾種常見的鎖:公平鎖和非公平鎖、可重入鎖、獨(dú)享鎖/共享鎖、互斥鎖/讀寫鎖、樂觀鎖/悲觀鎖、分段鎖、偏向鎖/輕量級(jí)鎖/重量級(jí)鎖、自旋鎖。

1、公平鎖和非公平鎖

公平鎖是指多個(gè)線程按照申請鎖的順序來獲取鎖。
非公平鎖是指多個(gè)線程獲取鎖的順序并不是按照申請鎖的順序,有可能后申請的線程比先申請的線程優(yōu)先獲取鎖。有可能,會(huì)造成優(yōu)先級(jí)反轉(zhuǎn)或者饑餓現(xiàn)象。
對于Java ReentrantLock而言,通過構(gòu)造函數(shù)指定該鎖是否是公平鎖,默認(rèn)是非公平鎖的優(yōu)點(diǎn)在于吞吐量比公平鎖大。
對于synchronized而言,也是一種非公平鎖。由于其并不像ReentrantLock是通過AQS的來實(shí)現(xiàn)線程調(diào)度,所以并沒有任何辦法使其變成公平鎖。

package com.xxxx.reids.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/***
 * @title ReentrantLockFair
 * @desctption 公平鎖
 * @author Kelvin
 * @create 2023/5/29 16:10
 **/
public class ReentrantLockFair {

    public static void main(String[] args) {
        //true表示公平鎖
        Lock lock = new ReentrantLock(true);
        for (int i = 0; i < 3; i++) {
            new Thread(){
                @Override
                public void run() {
                    for (int j = 0; j < 2; j++) {
                        lock.lock();
                        System.out.println(Thread.currentThread().getName());
                        lock.unlock();
                    }
                }
            }.start();
        }
    }

}

```java
package com.xxxx.reids.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/***
 * @title ReentrantLockFair
 * @desctption 非公平鎖
 * @author Kelvin
 * @create 2023/5/29 16:10
 **/
public class ReentrantLockFair {

    public static void main(String[] args) {
        //false表示非公平鎖
        Lock lock = new ReentrantLock(false);
        for (int i = 0; i < 3; i++) {
            new Thread(){
                @Override
                public void run() {
                    for (int j = 0; j < 2; j++) {
                        lock.lock();
                        System.out.println(Thread.currentThread().getName());
                        lock.unlock();
                    }
                }
            }.start();
        }
    }

}

2、可重入鎖

可重入鎖又名遞歸鎖,是指在同一個(gè)線程在外層方法獲取鎖的時(shí)候,在進(jìn)入內(nèi)層方法會(huì)自動(dòng)獲取鎖(就是可以重新進(jìn)入獲得鎖)對于Java ReentrantLock而言, 其名字是Reentrant Lock即是重新進(jìn)入鎖。對于synchronized而言,也是一個(gè)可重入鎖??芍厝腈i的一個(gè)好處是可一定程度避免死鎖
(可重入鎖,指的是以線程為單位,當(dāng)一個(gè)線程獲取對象鎖之后,這個(gè)線程可以再次獲取本對象上的鎖,而其他的線程是不可以的。)

synchronized void setA() throws Exception{
Thread.sleep(1000);
setB();
}
synchronized void setB() throws Exception{
Thread.sleep(1000);
}

/***
 * @title ReentrantLockTest
 * @desctption 可重入鎖測試
 * @author Kelvin
 * @create 2023/5/29 16:29
 **/
public class ReentrantLockTest {

    public static void main(String[] args) {
        Object obj = new Object();
        new Thread(() -> {
            //第一次加鎖
            synchronized (obj) {
                System.out.println(Thread.currentThread().getName() + "第一層");
                //第二次加鎖,此時(shí)obj對象處于鎖定狀態(tài),但是當(dāng)前線程仍然可以進(jìn)入,避免死鎖
                synchronized (obj) {
                    int i = 1 / 0;
                    System.out.println(Thread.currentThread().getName() + "第二層");
                }
            }
        }, "t1").start();
        new Thread(() -> {
            //第一次加鎖
            synchronized (obj) {
                System.out.println(Thread.currentThread().getName() + "第一層");
                //第二次加鎖,此時(shí)obj對象處于鎖定狀態(tài),但是當(dāng)前線程仍然可以進(jìn)入,避免死鎖
                synchronized (obj) {
                    System.out.println(Thread.currentThread().getName() + "第二層");
                }
            }
        }, "t2").start();
    }

}


練習(xí):用ReentrantLock測試可重入鎖

3、獨(dú)享鎖/共享鎖

獨(dú)享鎖是指該鎖一次只能被一個(gè)線程所持有;共享鎖是指該鎖可被多個(gè)線程所持有

對于Java ReentrantLock而言,其是獨(dú)享鎖。但是對于Lock的另一個(gè)實(shí)現(xiàn)類ReadWriteLock,其讀鎖是共享鎖,其寫鎖是獨(dú)享鎖。讀鎖的共享鎖可保證并發(fā)讀是非常高效的,讀寫、寫讀 、寫寫的過程是互斥的。獨(dú)享鎖與共享鎖也是通過AQS來實(shí)現(xiàn)的,通過實(shí)現(xiàn)不同的方法,來實(shí)現(xiàn)獨(dú)享或者共享。對于synchronized而言,當(dāng)然是獨(dú)享鎖。
(讀鎖使用共享模式;寫鎖使用獨(dú)占模式;讀鎖可以在沒有寫鎖的時(shí)候被多個(gè)線程同時(shí)持有,寫鎖是獨(dú)占的。當(dāng)有讀鎖時(shí),寫鎖就不能獲得;而當(dāng)有寫鎖時(shí),除了獲得寫鎖的這個(gè)線程可以獲得讀鎖外,其他線程不能獲得讀鎖)

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/***
 * @title WriteAndReedLockTest
 * @desctption 讀寫鎖
 * @author kelvin
 * @create 2023/5/29 16:58
 **/
public class WriteAndReedLockTest {
    private static ReentrantReadWriteLock reentrantReadWriteLock= new ReentrantReadWriteLock();
    private static ExecutorService executorService = Executors.newFixedThreadPool(3);
    //執(zhí)行三個(gè)線程進(jìn)行讀寫操作,并設(shè)置一個(gè)屏障,線程依次準(zhǔn)備就緒后未獲取鎖之前都在等待,當(dāng)?shù)谌齻€(gè)線程執(zhí)行 cyclicBarrier.await();后屏障解除,三個(gè)線程同時(shí)執(zhí)行。
    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
    private static Integer i = 100;
    public static void main(String[] args) {
        executorService.execute(
                () ->{
                    read();
                }
        );
        executorService.execute(
                () ->{
                    write();
                }
        );
        executorService.execute(
                () ->{
                    read();
                }
        );
    }

    private static void read(){
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        //獲取讀鎖
        reentrantReadWriteLock.readLock().lock();
        System.out.println("Read," + Thread.currentThread().getName() + ",i = " + i);
        reentrantReadWriteLock.readLock().unlock();
    }

    private static void write(){
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        //獲取寫鎖
        reentrantReadWriteLock.writeLock().lock();
        i ++;
        System.out.println("Write," + Thread.currentThread().getName() + ",i = " + i);
        reentrantReadWriteLock.writeLock().unlock();
    }
}

4、互斥鎖/讀寫鎖

獨(dú)享鎖/共享鎖就是一種廣義的說法,互斥鎖/讀寫鎖就是具體的實(shí)現(xiàn)?;コ怄i在Java中的具體實(shí)現(xiàn)就是ReentrantLock;讀寫鎖在Java中的具體實(shí)現(xiàn)就是Read/WriteLock。

5、樂觀鎖/悲觀鎖

樂觀鎖與悲觀鎖不是指具體的什么類型的鎖,而是指看待并發(fā)同步的角度。

  • 悲觀鎖:總是假設(shè)最壞的情況,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)阻塞直到它拿到鎖。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。再比如 Java 里面的同步原語 synchronized 關(guān)鍵字的實(shí)現(xiàn)也是悲觀鎖
  • 樂觀鎖:顧名思義,就是很樂觀,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改,所以不會(huì)上鎖,但是在更新的時(shí)候會(huì)判斷一下在此期間別人有沒有去更新這個(gè)數(shù)據(jù),可以使用版本號(hào)等機(jī)制。樂觀鎖適用于多讀的應(yīng)用類型,這樣可以提高吞吐量,像數(shù)據(jù)庫提供的類似于 write_condition 機(jī)制,其實(shí)都是提供的樂觀鎖。在 Java中 java.util.concurrent.atomic 包下面的原子變量類就是使用了樂觀鎖的一種實(shí)現(xiàn)方式 CAS 實(shí)現(xiàn)的
  • 在Java中java.util.concurrent.atomic包下面的原子變量類就是使用了樂觀鎖的一種實(shí)現(xiàn)方式CAS(Compare and Swap 比較并交換)實(shí)現(xiàn)的。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/***
 * @title AtomicExample
 * @desctption 樂觀鎖/悲觀鎖
 * @author Kelvin
 * @create 2023/5/29 17:08
 **/
public class AtomicExample {
    private static Integer m = 1;
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 1000; i++) {
            executorService.submit(
                    () -> {
                        m ++;
                    }
            );
        }
        TimeUnit.SECONDS.sleep(2);
        System.out.println(m);
    }
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/***
 * @title AtomicExample
 * @desctption 樂觀鎖/悲觀鎖
 * @author Kelvin
 * @create 2023/5/29 17:08
 **/
public class AtomicExample {
    private static AtomicInteger m = new AtomicInteger(1);
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 1000; i++) {
            executorService.submit(
                    () -> {
                        m.incrementAndGet();
                    }
            );
        }
        TimeUnit.SECONDS.sleep(2);
        System.out.println(m.get());
    }
}

6、分段鎖

分段鎖其實(shí)是一種鎖的設(shè)計(jì),并不是具體的一種鎖,對于ConcurrentHashMap而言,其并發(fā)的實(shí)現(xiàn)就是通過分段鎖的形式來實(shí)現(xiàn)高效的并發(fā)操作,ConcurrentHashMap中的分段鎖稱為Segment,它即類似于HashMap(JDK7與JDK8中HashMap的實(shí)現(xiàn))的結(jié)構(gòu),即內(nèi)部擁有一個(gè)Entry數(shù)組,數(shù)組中的每個(gè)元素又是一個(gè)鏈表;同時(shí)又是一個(gè)ReentrantLock(Segment繼承了ReentrantLock)。當(dāng)需要put元素的時(shí)候,并不是對整個(gè)HashMap進(jìn)行加鎖,而是先通過hashcode來知道他要放在那一個(gè)分段中,然后對這個(gè)分段進(jìn)行加鎖,所以當(dāng)多線程put的時(shí)候,只要不是放在一個(gè)分段中,就實(shí)現(xiàn)了真正的并行的插入。但是,在統(tǒng)計(jì)size的時(shí)候,可就是獲取HashMap全局信息的時(shí)候,就需要獲取所有的分段鎖才能統(tǒng)計(jì)。

分段鎖的設(shè)計(jì)目的是細(xì)化鎖的粒度,當(dāng)操作不需要更新整個(gè)數(shù)組的時(shí)候,就僅僅針對數(shù)組中的一項(xiàng)進(jìn)行加鎖操作。

7、偏向鎖/輕量級(jí)鎖/重量級(jí)鎖

這三種鎖是指鎖的狀態(tài),并且是針對synchronized。在Java 5通過引入鎖升級(jí)的機(jī)制來實(shí)現(xiàn)高效synchronized。這三種鎖的狀態(tài)是通過對象監(jiān)視器在對象頭中的字段來表明的。

  • 偏向鎖是指一段同步代碼一直被一個(gè)線程所訪問,那么該線程會(huì)自動(dòng)獲取鎖。降低獲取鎖的代價(jià)。
  • 輕量級(jí)鎖是指當(dāng)鎖是偏向鎖的時(shí)候,被另一個(gè)線程所訪問,偏向鎖就會(huì)升級(jí)為輕量級(jí)鎖,其他線程會(huì)通過自旋的形式嘗試獲取鎖,不會(huì)阻塞,提高性能。
  • 重量級(jí)鎖是指當(dāng)鎖為輕量級(jí)鎖的時(shí)候,另一個(gè)線程雖然是自旋,但自旋不會(huì)一直持續(xù)下去,當(dāng)自旋一定次數(shù)的時(shí)候,還沒有獲取到鎖,就會(huì)進(jìn)入阻塞,該鎖膨脹為重量級(jí)鎖。重量級(jí)鎖會(huì)讓其他申請的線程進(jìn)入阻塞,性能降低。

8、自旋鎖

在Java中,自旋鎖是指嘗試獲取鎖的線程不會(huì)立即阻塞,而是采用循環(huán)的方式去嘗試獲取鎖,這樣的好處是減少線程上下文切換的消耗,缺點(diǎn)是循環(huán)會(huì)消耗CPU文章來源地址http://www.zghlxwxcb.cn/news/detail-464116.html

到了這里,關(guān)于《微服務(wù)實(shí)戰(zhàn)》 第二十六章 Java鎖的分類的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • vue 3 第二十六章:樣式(scoped及樣式穿透)

    vue 3 第二十六章:樣式(scoped及樣式穿透)

    在 Vue 中,我們可以使用 scoped 特性來給組件的樣式添加作用域。通過為組件的 style 標(biāo)簽添加 scoped 特性,我們可以確保組件的樣式僅應(yīng)用于該組件的模板中,而不會(huì)影響其他組件或全局樣式。 在上面的例子中, .example 類的樣式只會(huì)應(yīng)用于該組件的模板中,而不會(huì)影響其他組

    2024年02月06日
    瀏覽(36)
  • ChatGPT 與生成式 AI 的崛起:第二十六章到第三十三章

    ChatGPT 與生成式 AI 的崛起:第二十六章到第三十三章

    原文:Rise of Generative AI and ChatGPT 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 恐怖分子、罪犯、警察、國防、執(zhí)法機(jī)構(gòu)、工程師、作家和學(xué)生等都在使用 ChatGPT,這是來自 OpenAI 的強(qiáng)大自然語言人工智能工具,作為他們?nèi)粘9ぷ鞯闹匾M成部分。自去年 11 月底發(fā)布以來,這種生成式人工智

    2024年01月24日
    瀏覽(224)
  • VRRP技術(shù)和浮動(dòng)路由(第二十六課)

    一、浮動(dòng)路由 1、浮動(dòng)路由概述 1)浮動(dòng)路由是什么 -浮動(dòng)路由又稱為路由備份,由兩條或多條鏈路組成浮動(dòng)路由 -浮動(dòng)路由指配置兩條靜態(tài)路由,這兩條靜態(tài)路由的目的地址相同,但是下一跳地址不同兩條靜態(tài)路由 -給這兩條靜態(tài)路由設(shè)置不同的優(yōu)先級(jí),優(yōu)先級(jí)高的那條靜態(tài)路

    2024年02月15日
    瀏覽(28)
  • 服務(wù)(第二十六篇)redis的主從復(fù)制、哨兵、集群

    服務(wù)(第二十六篇)redis的主從復(fù)制、哨兵、集群

    主從復(fù)制,是指將一臺(tái)Redis服務(wù)器的數(shù)據(jù),復(fù)制到其他的Redis服務(wù)器。前者稱為主節(jié)點(diǎn)(Master),后者稱為從節(jié)點(diǎn)(Slave);數(shù)據(jù)的復(fù)制是單向的,只能由主節(jié)點(diǎn)到從節(jié)點(diǎn)。 原理: 主從關(guān)系確定好后,開啟從節(jié)點(diǎn)時(shí),會(huì)發(fā)送一個(gè)sync的同步命令給主節(jié)點(diǎn),主節(jié)點(diǎn)接收到后會(huì)把redis內(nèi)存

    2024年02月06日
    瀏覽(27)
  • 學(xué)C的第二十六天【指針的進(jìn)階(二)】

    學(xué)C的第二十六天【指針的進(jìn)階(二)】

    ========================================================================= 相關(guān)代碼gitee自取 :C語言學(xué)習(xí)日記: 加油努力 (gitee.com) ?========================================================================= 接上期 : 學(xué)C的第二十五天【指針的進(jìn)階(一)】_高高的胖子的博客-CSDN博客 ?================================

    2024年02月13日
    瀏覽(38)
  • C語言第二十六彈---字符串函數(shù)(下)

    C語言第二十六彈---字符串函數(shù)(下)

    ? 個(gè)人主頁: ? 熬夜學(xué)編程的小林 ?? 系列專欄: ? 【C語言詳解】 ? 【數(shù)據(jù)結(jié)構(gòu)詳解】 目錄 1、strncat 函數(shù)的使用 2、strncmp 函數(shù)的使用 3、strstr 函數(shù)的使用和模擬實(shí)現(xiàn) 4、strtok 函數(shù)的使用 5、strerror 函數(shù)的使用 6、perror 函數(shù)的使用 總結(jié) ? Appends the first num characters of sourc

    2024年02月20日
    瀏覽(24)
  • 嵌入式學(xué)習(xí)第二十六天?。ňW(wǎng)絡(luò)傳輸:TCP編程)

    嵌入式學(xué)習(xí)第二十六天!(網(wǎng)絡(luò)傳輸:TCP編程)

    ? ? ? ? socket ? -? connect? -? send? -? recv ? -? close ? ? ? ? socket ? -? bind ? -? listen ? -? accept ? - recv ? -? send ? -? close ????????1. connect: ? ? ? ? ? ? ? 功能: 發(fā)送鏈接請求 ? ? ? ? ? ? ? 參數(shù): ? ? ? ? ? ? ? ? ? sockfd: 套接字文件描述符 ? ? ? ? ? ? ? ? ?

    2024年03月09日
    瀏覽(40)
  • 開發(fā)工具篇第二十六講:使用IDEA進(jìn)行本地調(diào)試和遠(yuǎn)程調(diào)試

    Debug用來追蹤代碼的運(yùn)行流程,通常在程序運(yùn)行過程中出現(xiàn)異常,啟用Debug模式可以分析定位異常發(fā)生的位置,以及在運(yùn)行過程中參數(shù)的變化;并且在實(shí)際的排錯(cuò)過程中,還會(huì)用到Remote Debug。 本文是開發(fā)工具篇第二十六講,主要介紹基于IDEA的Debug和Remote Debug的技巧。

    2024年02月16日
    瀏覽(99)
  • MFC第二十六天 CRgn類簡介與開發(fā)、封裝CMemoryDC類并應(yīng)用開發(fā)

    MFC第二十六天 CRgn類簡介與開發(fā)、封裝CMemoryDC類并應(yīng)用開發(fā)

    CRgn類是MFC(Microsoft Foundation Classes)中的一個(gè)圖形區(qū)域類。該類用于創(chuàng)建和操作圖形區(qū)域,可以表示各種形狀的區(qū)域,如矩形、橢圓、多邊形等。 CRgnDlg.h CRgnDlg.cpp CircleRgnDlg.h CircleRgnDlg.cpp CCircleRgnDlg.h CCircleRgnDlg.cpp CFlashDlg.h CFlashDlg.cpp QQDlg.h QQDlg.cpp CPaintDC,CClientDC,CWindowDC,CMemory

    2024年02月14日
    瀏覽(22)
  • 【微服務(wù)實(shí)戰(zhàn)之Docker容器】第四章-【微服務(wù)實(shí)戰(zhàn)之Docker容器】第三章-鏡像倉庫

    【微服務(wù)實(shí)戰(zhàn)之Docker容器】第四章-【微服務(wù)實(shí)戰(zhàn)之Docker容器】第三章-鏡像倉庫

    【微服務(wù)實(shí)戰(zhàn)之Docker容器】第一章-下載及安裝 Docker掛載主機(jī)目錄訪問如果出現(xiàn)cannot open directory .: Permission denied解決辦法: 在掛載目錄后多加一個(gè)–privileged=true參數(shù)即可 如果是CentOS7安全模塊會(huì)比之前系統(tǒng)版本加強(qiáng),不安全的會(huì)先禁止,所以目錄掛載的情況被默認(rèn)為不安全的

    2024年02月07日
    瀏覽(23)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包