ReentrantLock
ReentrantLock是什么
ReenTrantLock
实现了Lock
接口,是一个可重入且独占式的锁,和synchronized
关键字类似,不过 ReenTrantLock
更灵活,更强大, 增加了轮询, 超时, 中断, 公平锁和非公平锁等高级功能.
public class ReentrantLock implements Lock, java.io.Serializable {}
ReenTrantLock
里面有一个内部类Sync
, Sync
继承了AQS, 添加锁和释放锁的大部门操作实际上都是再Sync
中实现的. Sync
有公平锁FairSync
和非公平锁NonfairSync
两个子类
ReentrantLock
默认使用非公平锁,也可以通过构造器来显式的指定使用公平锁。
公平锁和非公平锁有什么区别
- 公平锁: 锁被释放后, 先申请的线程得到锁.性能差一点, 因为公平锁为了保证时间上的绝对顺序, 上下文切换更加频繁
- 非公平锁: 锁被释放后, 后申请的线程可能会先获取到锁, 是随机或者按照其他优先级排序的. 性能更哈皮, 但可能会导致某些线程永辉无法获取到锁.
synchronizedj 和 ReemtrantLock
两者都是可重入锁
可重入锁 也称递归锁, 指的是线程可以再次获取自己的内部锁, 比如一个线程获得了某个对象的锁, 此时这个对象锁还没有释放, 当其再次想要获取这个对象的锁的时候还是可以获取的, 如果是不可重入锁的话, 就会造成死锁.
JDK提供的所有线程的Lock
实现类, 包括synchronized
关键字锁都是可重入的.
synchronized 依赖于 JVM 而 ReentrantLock 依赖于API
synchronized
是依赖于JVM实现的, 虚拟机团队在JDK1.6 为synchronized
关键字进行了很多优化, 但是这些优化都是虚拟机层面实现的, 并没有直接暴露给我们.
ReentrantLock
是JDK层面实现的(也就是API层面, 需要lock()和unlock()方法配合try/finally语句块来完成), 所以我们可以通过查看它的源代码, 来看它是如何实现的.
ReentrantLock 比 synchronized 增加了一些高级功能
ReentrantLock 比 synchronized 增加了一些高级功能. 主要来说主要有三点:
- 等待可中断:
ReentrantLock
提供了一种能够中断等待所的线程机制, 通过lock.lockInterruptibly()
来实现这个机制. 也就是说正在等待的线程可以选择放弃等待,改为处理其他的事情. - 可实现公平锁:
ReentrantLock
可以指定是公平锁还是非公平锁. 而synchronized
只能说非公平锁. 所谓的公平锁就算先等待的线程先获得锁.ReentrantLock
默认情况是非公平的, 可以通过ReentrantLock
类的ReentrantLock(boolen fair)
构造方法来指定是否公平. - 可实现选择性通知(锁可以绑定多个条件):
synchronized
关键字与wait()
和notify()
/notifyAll
方法相结合可以实现等待/通知机制.ReentrantLock
类当然也可以实现,但是需要借助Condition
接口与newCondition
方法.