欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java顯式鎖詳情

 更新時間:2021年09月10日 09:39:08   作者:IT王小二  
這篇文章主要詳細的介紹了shenJava顯式鎖常用的api及標準用法,感興趣的朋友,需要的朋友可以參考下面文章里的內容

Java顯式鎖

一、顯式鎖

什么是顯式鎖?

由自己手動獲取鎖,然后手動釋放的鎖。

有了 synchronized(內置鎖) 為什么還要 Lock(顯示鎖)?

使用 synchronized 關鍵字實現(xiàn)了鎖功能的,使用 synchronized 關鍵字將會隱式地獲取鎖,但是它將鎖的獲取和釋放固化了,也就是先獲取再釋放。

與內置加鎖機制不同的是,Lock 提供了一種無條件的、可輪詢的、定時的以及可中斷的鎖獲取操作,所有加鎖和解鎖的方法都是顯式的。

二、Lock的常用api

方法名稱 描述
void lock() 獲取鎖
void lockInterruptibly() throws InterruptedException 可中斷的獲取鎖,和lock()方法的不同之處在于該方法會響應中斷,即在鎖的獲取中可以中斷當前線程
boolean tryLock() 嘗試非阻塞的獲取鎖,調用該方法后立刻返回,如果能夠獲取則返回true,否則返回false
boolean tryLock(long time, TimeUnit unit) throws InterruptedException 超時獲取鎖,當前線程會在以下三種情況下會返回:
1. 當前線程在超時時間內獲得了鎖
2.當前線程在超市時間內被中斷
3. 超時時間結束,返回false
void unlock(); 釋放鎖

三、Lock的標準用法

lock.lock();
try {
    // 業(yè)務邏輯
} finally {
    lock.unlock();
}

  • finally 塊中釋放鎖,目的是保證在獲取到鎖之后,最終能夠被釋放。
  • 不要將獲取鎖的過程寫在 try 塊中,因為如果在獲取鎖(自定義鎖的實現(xiàn))時發(fā)生了異常,異常拋出的同時,也會導致鎖無故釋放。

四、ReentrantLock(可重入鎖)

Lock接口常用的實現(xiàn)類是 ReentrantLock。

示例代碼:主線程100000次減,子線程10萬次加。

public class ReentrantLockTest {

    private Lock lock = new ReentrantLock();
    private int count = 0;

    public int getCount() {
        return count;
    }

    private static class ReentrantLockThread extends Thread {
        private ReentrantLockTest reentrantLockTest;

        public ReentrantLockThread(ReentrantLockTest reentrantLockTest) {
            this.reentrantLockTest = reentrantLockTest;
        }

        @Override
        public void run() {
            for (int i = 0; i < 100000; i++) {
                reentrantLockTest.incr();
            }
            System.out.println(Thread.currentThread().getName() + " end, count =  " + reentrantLockTest.getCount());
        }
    }

    private void incr() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    private void decr() {
        lock.lock();
        try {
            count--;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ReentrantLockTest reentrantLockTest = new ReentrantLockTest();
        new ReentrantLockThread(reentrantLockTest).start();

        for (int i = 0; i < 100000; i++) {
            // 遞減100000
            reentrantLockTest.decr();
        }
        System.out.println(Thread.currentThread().getName() + " count =  " + reentrantLockTest.getCount());
    }
}

1. 鎖的可重入性

簡單地講就是:“同一個線程對于已經(jīng)獲得到的鎖,可以多次繼續(xù)申請到該鎖的使用權”。而 synchronized 關鍵字隱式的支持重進入,比如一個 synchronized 修飾的遞歸方法,在方法執(zhí)行時,執(zhí)行線程在獲取了鎖之后仍能連續(xù)多次地獲得該鎖

同樣,ReentrantLock 在調用 lock()方法時,已經(jīng)獲取到鎖的線程,能夠再次調用lock()方法獲取鎖而不被阻塞

2. 公平鎖和非公平鎖

  • 如果在時間上,先對鎖進行獲取的請求一定先被滿足,那么這個鎖是公平的,反之,是不公平的。公平的獲取鎖,也就是等待時間最長的線程最優(yōu)先獲取鎖,也可以說鎖獲取是順序的。
  • ReentrantLock 提供了一個構造函數(shù),能夠控制鎖是否是公平的(缺省為不公平鎖)。事實上,公平的鎖機制往往沒有非公平的效率高。
  • 在激烈競爭的情況下,非公平鎖的性能高于公平鎖的性能的一個原因是:在恢復一個被掛起的線程與該線程真正開始運行之間存在著嚴重的延遲。
  • 假設線程 A 持有一個鎖,并且線程 B 請求這個鎖,由于這個鎖已被線程 A 持有,因此 B 將被掛起。當 A 釋放鎖時,B 將被喚醒,因此會再次嘗試獲取鎖。與此同時,如果 C 也請求這個鎖,那么 C 很可能會在 B 被完全喚醒之前獲得、使用以及釋放這個鎖,這樣的情況是一種“雙贏”的局面:B 獲得鎖的時刻并沒有推遲,C 更早地獲得了鎖,完成了自己的任務,然后釋放了鎖,并且吞吐量也獲得了提高。

五、ReentrantReadWriteLock(讀寫鎖)

ReentrantReadWriteLock 是 ReadWriteLock 的實現(xiàn)類。

之前提到鎖基本都是排他鎖,這些鎖在同一時刻只允許一個線程進行訪問,而讀寫鎖在同一時刻可以允許多個讀線程訪問但是在寫線程訪問時,所有的讀線程和其他寫線程均被阻塞。讀寫鎖維護了一對鎖,一個讀鎖和一個寫鎖,通過分離讀鎖和寫鎖,使得并發(fā)性相比一般的排他鎖有了很大提升。

讀鎖不排斥讀鎖,但是排斥寫鎖;寫鎖即排斥讀鎖也排斥寫鎖。

private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock getLock = lock.readLock(); // 讀鎖
private final Lock setLock = lock.writeLock(); // 寫鎖


至于上鎖、解鎖與 ReentrantLock 使用方式一致。

六、Condition

  • 任意一個 Java 對象,都擁有一組監(jiān)視器方法(定義在 java.lang.Object 上),主要包括 wait()、wait(long timeout)、notify()以及 notifyAll()方法,這些方法與 synchronized 同步關鍵字配合,可以實現(xiàn)等待/通知模式。
  • Condition 接口也提供了類似 Object 的監(jiān)視器方法,與 Lock 配合可以實現(xiàn)等待/通知模式。

常用api

方法名稱 描述
void await() throws InterruptedException 使當前線程進入等待狀態(tài)直到被通知(signal)或中斷
void signal() 喚醒一個等待的線程
void signalAll() 喚醒所有等待的線程

示例代碼,主線程調用方法喚醒兩個子線程。

public class ConditionTest {

    private volatile boolean flag = false;
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    private void task1() {
        lock.lock();
        try {
            try {
                System.out.println(Thread.currentThread().getName() + " 等待中");
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 等待結束");
            System.out.println("發(fā)送郵件");
        } finally {
            lock.unlock();
        }
    }

    private void task2() {
        lock.lock();
        try {
            try {
                System.out.println(Thread.currentThread().getName() + " 等待中");
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 等待結束");
            System.out.println("發(fā)送短信");
        } finally {
            lock.unlock();
        }
    }

    private void updateFlag() {
        lock.lock();
        try {
            this.flag = true;
            this.condition.signalAll();
        }finally {
            lock.unlock();
        }
    }

    private static class ConditionThread1 extends Thread {
        private ConditionTest conditionTest;
        public ConditionThread1(ConditionTest conditionTest) {
            this.conditionTest = conditionTest;
        }

        @Override
        public void run() {
            if (!conditionTest.flag) {
                conditionTest.task1();
            }
        }
    }

    private static class ConditionThread2 extends Thread {
        private ConditionTest conditionTest;
        public ConditionThread2(ConditionTest conditionTest) {
            this.conditionTest = conditionTest;
        }

        @Override
        public void run() {
            if (!conditionTest.flag) {
                conditionTest.task2();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ConditionTest conditionTest = new ConditionTest();
        new ConditionThread1(conditionTest).start();
        new ConditionThread2(conditionTest).start();
        Thread.sleep(1000);
        System.out.println("flag 改變。。。");
        conditionTest.updateFlag();
    }
}

以上就是Java顯式鎖詳情的詳細內容,更多關于Java顯式鎖的資料請關注腳本之家其它相關文章!

相關文章

  • 深入理解Java 線程池

    深入理解Java 線程池

    這篇文章主要介紹了Java 線程池的相關資料,文中講解非常細致,幫助大家更好的理解和學習,感興趣的朋友可以了解下
    2020-07-07
  • java類中生成jfreechart,返回圖表的url地址 代碼分享

    java類中生成jfreechart,返回圖表的url地址 代碼分享

    這篇文章介紹了java類中生成jfreechart,返回圖表的url地址的代碼,有需要的朋友可以參考一下
    2013-08-08
  • SpringBoot集成 Prometheus進行高效監(jiān)控的實現(xiàn)

    SpringBoot集成 Prometheus進行高效監(jiān)控的實現(xiàn)

    Prometheus作為一個開源的監(jiān)控和告警工具,以其強大的數(shù)據(jù)采集、存儲和查詢能力,受到了眾多開發(fā)者的青睞,本文主要介紹了SpringBoot集成 Prometheus進行高效監(jiān)控的實現(xiàn),感興趣的可以了解一下
    2024-07-07
  • 解決SpringBoot自定義攔截器和跨域配置沖突的問題

    解決SpringBoot自定義攔截器和跨域配置沖突的問題

    這篇文章主要介紹了解決SpringBoot自定義攔截器和跨域配置沖突的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 關于SpringCloud的微服務以及組件詳解

    關于SpringCloud的微服務以及組件詳解

    這篇文章主要介紹了關于SpringCloud的微服務以及組件詳解,是一個更高層次的、 架構視角的綜合性大型項目, 他的目標是構建一套標準化的微服務解決方案,需要的朋友可以參考下
    2023-05-05
  • java中的移位運算符心得總結

    java中的移位運算符心得總結

    這篇文章介紹了java中的移位運算符,有需要的朋友可以參考一下
    2013-11-11
  • java編程常用技術(推薦)

    java編程常用技術(推薦)

    下面小編就為大家?guī)硪黄猨ava編程常用技術(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06
  • Java正確實現(xiàn)一個單例設計模式的示例

    Java正確實現(xiàn)一個單例設計模式的示例

    今天小編就為大家分享一篇關于Java正確實現(xiàn)一個單例設計模式的示例,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • 關于對Java正則表達式"\\"的理解

    關于對Java正則表達式"\\"的理解

    正則表達式中,\代表轉義字符,通常是轉義一些特殊字符,下面這篇文章主要給大家介紹了關于對Java正則表達式"\\"的相關理解,需要的朋友可以參考下
    2022-09-09
  • JAVA中的函數(shù)式接口Function和BiFunction詳解

    JAVA中的函數(shù)式接口Function和BiFunction詳解

    這篇文章主要介紹了JAVA中的函數(shù)式接口Function和BiFunction詳解,JDK的函數(shù)式接口都加上了@FunctionalInterface注解進行標識,但是無論是否加上該注解只要接口中只有一個抽象方法,都是函數(shù)式接口,需要的朋友可以參考下
    2024-01-01

最新評論