ReentrantLock源码剖析

ReentrantLock源码剖析

测试案例:

public class ReentrantLockDemo {

//    ReentrantLock lock = new ReentrantLock(); // 默认是非公平锁
 //    ReentrantLock lock = new ReentrantLock(true); // true:公平锁,false:非公平锁

    public static void main(String[] args) {
        new ReentrantLockDemo().exe();
    }

    public void exe() {
        Thread thread1 = new Thread(this::meal, "小 A");
        Thread thread2 = new Thread(this::meal, "小 B");
        Thread thread3 = new Thread(this::meal, "小 C");
        System.out.println("小 A 排队打餐");
        System.out.println("小 B 排队打餐");
        System.out.println("小 C 排队打餐");
        thread1.start();
        thread2.start();
        thread3.start();
    }

    public void meal() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " --> 开始打餐");
            System.out.println(Thread.currentThread().getName() + " --> 打餐中。。。");
            System.out.println(Thread.currentThread().getName() + " --> 打完餐,离开");
        } finally {
            lock.unlock();
        }
    }

//    private void sleep() {
//        try {
//            TimeUnit.SECONDS.sleep(1);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//    }
}

非公平锁运行结果:

小 A 排队打餐
小 B 排队打餐
小 C 排队打餐
小 A --> 开始打餐
小 A --> 打餐中。。。
小 A --> 打完餐,离开
小 C --> 开始打餐
小 C --> 打餐中。。。
小 C --> 打完餐,离开
小 B --> 开始打餐
小 B --> 打餐中。。。
小 B --> 打完餐,离开

公平锁运行结果:

小 A 排队打餐
小 B 排队打餐
小 C 排队打餐
小 A --> 开始打餐
小 A --> 打餐中。。。
小 A --> 打完餐,离开
小 B --> 开始打餐
小 B --> 打餐中。。。
小 B --> 打完餐,离开
小 C --> 开始打餐
小 C --> 打餐中。。。
小 C --> 打完餐,离开

源码剖析:

ReentrantLock底层基于AQS

// true: 公平锁,false:非公平锁
public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

公平锁和非公平锁的底层实现逻辑:

主要在获取锁:
java.util.concurrent.locks.ReentrantLock.FairSync#lock

// 公平锁
final void lock() {
    // 调⽤ AQS 的 acquire 排队等待获取锁,⼊参是 1
    // 说白了就是一上来先排队
    acquire(1);
}

java.util.concurrent.locks.ReentrantLock.NonfairSync#lock

// 非公平锁
final void lock() {
    // ⾸先⽴即尝试CAS获取锁
    if (compareAndSetState(0, 1))
        setExclusiveOwnerThread(Thread.currentThread());
    else
        // 调⽤ AQS 的 acquire 排队等待获取锁,⼊参是 1
        // 如果没有获取到锁,就老老实实的排队
        acquire(1);
}

底层操作的是state变量,state=0表示无锁状态,state!=0表示锁没有完全释放。

posted on 2024-09-01 13:32  ~码铃薯~  阅读(3)  评论(0编辑  收藏  举报

导航