Java ReentrantLock深度解析:原理与实战

0 下载量 4 浏览量 更新于2024-08-28 收藏 181KB PDF 举报
"带你看看Java的锁(一)-ReentrantLock" 本文主要探讨Java中的ReentrantLock,这是一种可重入的互斥锁,属于Java并发包java.util.concurrent.locks中的核心类。ReentrantLock提供了比内置的synchronized关键字更高级、更灵活的锁定机制。 **ReentrantLock简介** ReentrantLock,顾名思义,"重入"表示一个线程已经获得了锁,如果它尝试再次获取该锁,锁的状态会允许它继续。这与synchronized不同,synchronized在尝试获取已被其持有的锁时会抛出死锁异常。ReentrantLock通过AQS(AbstractQueuedSynchronizer)内部的state字段来跟踪锁的持有状态。 **Synchronized对比** ReentrantLock和synchronized都是用于控制多线程对共享资源的访问,但ReentrantLock提供了更多特性。synchronized由JVM直接实现,而ReentrantLock由JDK提供,因此ReentrantLock更具有扩展性。它可以显式地获取和释放锁,支持公平锁和非公平锁策略,具备尝试获取锁的超时功能,以及线程中断处理机制。然而,使用ReentrantLock时,开发者需要确保在finally块中正确释放锁,以防止资源泄漏。 **公平锁与非公平锁** ReentrantLock可以通过构造函数选择公平锁或非公平锁。公平锁保证按照线程等待队列的顺序分配锁,而非公平锁则不保证这一顺序,可能会有更高的吞吐量,但可能导致饥饿现象。 **构造函数** ReentrantLock的构造函数允许指定公平策略: ```java public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } ``` 默认情况下,ReentrantLock是非公平的。 **lock()方法** - `lock()`:非公平锁的加锁方法,尝试立即获取锁,如果失败则会被放入等待队列。 - `lockInterruptibly()`:与`lock()`类似,但在等待获取锁时能够响应中断,如果线程被中断,将会抛出InterruptedException。 - `tryLock()`:尝试获取锁,如果当前没有其他线程持有锁,立即返回true;否则,返回false,不会阻塞。 - `tryLock(long time, TimeUnit unit)`:尝试在指定时间内获取锁,如果在规定时间内获取成功,返回true,否则返回false,并可能在等待期间响应中断。 **unlock()方法** 释放锁,调用`unlock()`方法将减少持有锁的线程计数。如果计数为0,则释放锁,并唤醒等待队列中的下一个线程。 **Condition** ReentrantLock还支持多个条件变量,每个条件变量都有自己的等待队列。通过`newCondition()`方法可以创建新的Condition实例,这样线程可以在满足特定条件时等待,而其他线程可以通知它们。 **总结** ReentrantLock提供了比synchronized更丰富的功能,包括可选择的公平策略、显式锁获取和释放、支持中断和超时、以及多条件等待。然而,使用ReentrantLock需要更多的编程工作,因为它没有synchronized的自动管理能力。根据应用场景,开发者可以选择更适合的同步机制。