ReentrantLock与Synchronized

ReentrantLock重入锁

​ reentrantLock是一种显式锁,与synchronized隐式锁对应,ReentrantLock实现基于AQS(AbstractQueueSynchronizer:队列同步器)通过对tryAcquire和tryRelease的重写实现了锁机制和重入机制,默认非公平锁.

方法 说明
lock 获取锁,如果锁不可用,那么当前线程会休眠直到获取到锁为止
lockInterruptibly 可中断地获取锁,如果当前线程发生interrupt,则释放锁
unlock 释放锁
newCondition 创建一个当前锁的条件监视器Condition,Condition实例用于控制当前Lock的线程队列的notify和wait

互斥锁(Mutex lock):通过阻塞线程来加锁,中断阻塞来解锁;

synchronized与ReentrantLock的优劣

ReentrantLock获得锁和释放锁的操作更加灵活,且具备独立的条件监视器,等待和唤醒线程的操作也更加方便和多样,在多线程情况下ReentrantLock效率比synchronized更高.

synchronized具备完备的语义,一个获取锁的操作一定会对应一个释放锁的操作,使用更加方便,简单.

ReentrantLock的条件监视器

Condition即条件,其在AQS中起到监视器(monitor)的作用,监视器用于监控一段同步的代码块,可以用于线程的阻塞和解除阻塞.

每当条件监视器增加一个等待线程的时候,该线程也会进入一个条件等待队列,下次signal方法调用的时候,会从队列里获取节点挨个唤醒.

方法 说明
await 当前线程进入等待状态,直到响应通知(signal)或者中断(Interrupt)
awaitUninterruptibly 当前线程进入等待状态,直到响应通知(signal)
awaitNanos(long) 指定一个单位为纳秒的超时时长,当前线程进入等待状态,直到响应通知,中断或超时,返回值为剩余时长,小于0则超时
awaitUntil(Date) 指定一个超时时刻,当前线程进入等待状态,直到响应通知,中断或者超时
signal/signalAll 对condition队列中的线程进行唤醒/唤醒全部

ReentrantLock结合Condition使用示例:力扣1114

public class P1114_PrintInOrder{
    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        //测试代码
        Foo foo = Foo.class.newInstance();
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        executorService.execute(() -> {
            try {
                foo.third(() -> System.out.println("first"));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        executorService.execute(() -> {
            try {
                foo.second(() -> System.out.println("second"));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        executorService.execute(() -> {
            try {
                foo.first(() -> System.out.println("third"));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        executorService.shutdown();
    }
    //力扣代码
    //leetcode submit region begin(Prohibit modification and deletion)
class Foo {
        
        ReentrantLock lock = new ReentrantLock(false);
        Condition condition = lock.newCondition();
        Integer state = 3;

    public Foo() {
        
    }

    public void first(Runnable printFirst) throws InterruptedException {
        lock.lock();
        while (state != 3) {
            condition.await();
        }
        state = 2;
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        condition.signalAll();
        lock.unlock();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        lock.lock();
        while (state != 2) {
            condition.await();
        }
        state = 1;
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        condition.signalAll();
        lock.unlock();
    }

    public void third(Runnable printThird) throws InterruptedException {
        lock.lock();
        while (state != 1) {
            condition.await();
        }
        state = 3;
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
        condition.signalAll();
        lock.unlock();
    }
}
//leetcode submit region end(Prohibit modification and deletion)

}

synchronized锁

synchronized关键字结合wait和notify的使用示例

public class Synchronize {

    /**
     * wait/notify方法的调用必须在该对象的锁(Monitor)中,否则抛出IllegalMonitorStateException异常
     * notify方法调用之后只有等待代码退出synchronized块后,其他线程才可以获取到锁
     */
    private final Object lock = new Object();
    private boolean envReady = false;

    public static void main(String[] args) {
        Synchronize sync = new Synchronize();
        sync.startWork();
        sync.prepareEnv();
    }
    
    public void startWork() {
        new WorkerThread().start();
    }
    
    public void prepareEnv() {
        new PrepareEnvThread().start();
    }
    
    private class WorkerThread extends Thread {
        public void run() {
            System.out.println("线程 WorkThread 等待获取锁");
            synchronized (lock) {
                try {
                    System.out.println("线程 WorkThread 获取到锁");
                    if (!envReady) {
                        System.out.println("线程 WorkThread 放弃锁,wait");
                        lock.wait();
                    }
                    System.out.println("线程 WorkThread 收到通知后继续执行");
                } catch (InterruptedException e) {
                    
                }
            }
        }
    }
    
    private class PrepareEnvThread extends Thread {
        public void run() {
            System.out.println("线程 PrepareEnvThread 等待获取锁");
            synchronized (lock) {
                System.out.println("线程 PrepareEnvThread 获取到锁");
                envReady = true;
                lock.notify();
                System.out.println("通知 WorkThread");
            }
        }
    }
    
}

posted @   Abserver  阅读(140)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
点击右上角即可分享
微信分享提示