ReentrantLock可重入锁与synchronized一样,都是互斥锁,即多个线程并发执行,只能有一个线程执行,其他线程需阻塞等待。
一、简介
对于大多数情况而言,ReentrantLock的性能优于synchronized关键字。这是因为ReentrantLock提供了更高的控制权,可以更容易地实现可重入和公平性等高级功能,从而使程序员可以更好地优化线程之间的协作和交互。 此外,ReentrantLock也支持超时和取消,这意味着程序员可以更容易地控制线程何时何地停止等待,以避免出现长时间阻塞的情况。相比之下,synchronized关键字只能基于当前锁的活动状态来确定何时释放锁,而这可能导致阻塞的时间过长。 但是,尽管ReentrantLock的性能更高,但它仍然有一定的开销,因为它需要管理额外的资源和数据结构。因此,如果只需要基本的互斥锁功能,那么synchronized关键字可能更为合适。 总之,ReentrantLock的性能优于synchronized的关键在于它的可配置性和灵活性,可以帮助程序员更好地处理复杂的线程间通信和交互。
二、ReentrantLock的常用接口方法
- lock():获取锁,如果锁已经被占用,则当前线程会被阻塞。
- unlock():释放锁,如果当前线程持有锁,则释放锁;如果当前线程并未持有锁,则抛出IllegalMonitorStateException异常。
- tryLock():尝试获取锁,如果锁未被占用,则获取锁并返回true;如果锁已经被占用,则立即返回false。
- tryLock(10, TimeUnit.SECONDS):该处会在10秒时间内处于等待中,但当调用B.interrupt()会被中断等待,并抛出InterruptedException。10秒时间内如果线程A释放锁,会获取到锁并返回true,否则10秒过后会获取不到锁并返回false。
- getState()方法来获取锁的状态,返回值是一个非负整数,表示当前被锁定的状态。如果返回值是0,表示锁未被任何线程占用;如果返回值是1,表示锁被一个线程持有;如果返回值是-1,表示锁被一个或多个线程等待获取。
- tryLock()方法尝试获取锁,如果当前锁可用,则返回true,并将锁保持住。同时还提供了
tryLock(long timeout, TimeUnit unit)
方法,用于在指定的时间内尝试获取锁。如果在指定的时间内获得了锁,则返回true;否则返回false。 总之,《ReentrantLock》类提供的tryLock()
方法可以用来快速尝试获取锁,在有限时间内尝试获取锁而不是无限期地等待,从而提高系统的整体效率。
其他方法,有兴趣的可以查看jdk的api文档
三、代码示例
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private final ReentrantLock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public void decrement() {
lock.lock();
try {
count--;
} finally {
lock.unlock();
}
}
public int getCount() {
return count;
}
}
在这个示例中,我们定义了一个ReentrantLock对象和一个整型变量count。increment()和decrement()方法分别用于增加和减少count的值。在方法中,我们使用lock.lock()获取锁,并在finally语句块中使用lock.unlock()释放锁。这样可以确保在增加或减少count的值时,不会出现线程安全问题。getCount()方法返回当前count的值。