ReentrantLock類

csm~/發表於2024-06-09

ReentrantLock

與synchronized相比有以下特點

  1. 可中斷
  2. 可以設定為公平鎖
  3. 支援多個條件變數

與sychronized一樣的

  1. 支援可重入鎖
  2. 可打斷鎖(避免死鎖):使用lockInterruptibly()方法

public class TestReentrant {
    private static ReentrantLock lock=new ReentrantLock();
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                System.out.println("嘗試獲取鎖");
                //如果沒有競爭此方法會獲取鎖
                //有競爭則進入阻塞佇列,可以被其他執行緒用interrupt方法打斷
                lock.lockInterruptibly();
            } catch (InterruptedException i) {
                System.out.println("沒有獲取到鎖");
                i.printStackTrace();
                return;
            }
            try {
                System.out.println("獲取鎖成功");
            } finally {
                lock.unlock();
            }
        });
        lock.lock();
        thread.start();	//主執行緒拿走鎖,使thread執行緒進入阻塞狀態
//        thread.interrupt();	//打斷該執行緒避免死鎖
    }
}

鎖超時

  1. 設定鎖超時
reentrantLock.tryLock(2, TimeUnit.SECONDS)//嘗試獲取鎖獲取鎖成功返回true,失敗返回false
reentrantLock.unLock();//該方法呼叫必須放在finally

條件變數:

可以建立多個,讓某個執行緒進入該條件變數等待。喚醒時可以指定喚醒某個執行緒

Condition condition = lock.newCondition();  //建立一個條件變數,讓某個執行緒在這裡等待
Condition condition1 = lock.newCondition();
 try {
 	condition.await();  //讓執行緒進入等待
   condition.signal(); //喚醒該條件變數中某個執行緒
   condition.signalAll();//喚醒該條件變數中的全部執行緒
} catch (InterruptedException e) {
   throw new RuntimeException(e);
} 

結合上面寫個案例


package devise;

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

/**
 *
 * 小明沒煙,要抽菸才能幹活
 * 小紅餓了,要吃外賣才能幹活。
 * 但是在同一個房間休息小明抽菸會有煙味,小紅吃不下。
 * 所以分了兩房間
 * 
 */

public class TestCorrectPostureStep {

    static ReentrantLock lock=new ReentrantLock();
    static Condition c1=lock.newCondition();//房間c1
    static Condition c2=lock.newCondition();//房間c2
    static boolean cigarette =false;
    static boolean takeout =false;

    public static void main(String[] args){
        //小明
        Thread t1=new Thread(()->{
            lock.lock();
            try {
                while (!cigarette){
                    System.out.println("煙沒到休息一會");
                    try {
                        c1.await(); //讓小明到c1休息室休息
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                System.out.println("煙到了,開始幹活");
            } finally {
                lock.unlock();
            }
        });
        //小紅
        Thread t2 =new Thread(()->{
            lock.lock();
            try {
                while (!takeout){
                    System.out.println("外賣沒到休息一會");
                    try {
                        c2.await();//讓小紅到c2休息室休息
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                System.out.println("外賣到了,開始幹活");
            }finally {
                lock.unlock();
            }
        });

        //送外賣執行緒
        Thread t3=new Thread(()->{
            lock.lock();
            try {
                Thread.sleep(2000);
                cigarette=true;
                c1.signal();//喚醒小紅讓小明幹活
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }finally {
                lock.unlock();
            }
        }); 
        //送煙執行緒
        Thread t4=new Thread(()->{
            lock.lock();
            try {
                Thread.sleep(2000);
                takeout=true;
                c2.signal(); //喚醒小明讓小明幹活
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }finally {
                lock.unlock();
            }
        });

        t1.start();
        t2.start();
        t3.start();
        t4.start();

    }}

相關文章