定义
1、重入锁ReentrantLock,支持重入的锁,标识该锁能够支持一个线程对资源重复加锁,该锁支持获取锁的公平性和非公平性选择。synchronized关键字隐式的支持重进入。
2、公平锁,在绝对的时间上,先对锁进行请求的一定先满足;反之,就是不公平的。公平锁机制往往没有非公平锁的效率高。公平锁往往没有非公平锁的效率高,公平锁能够减少”饥饿“发生的概率,等待越久的请求越是能够得到优先满足。
实现重入锁
重入锁是指任意线程在获取到锁之后能够再次获取该锁而不会被锁阻塞。该特性需要解决2个问题
- 线程再次获取锁:锁需要去识别获取锁的线程是否为当前占据锁的线程,如果是,则再次获取成功。
- 锁的最终释放:线程重复n次获取了锁,随后在第n次释放该锁后,其他线程能够再次获取到该锁。
锁的获取(以默认的非公平为例子)
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
// 获取锁的状态,
int c = getState();
// 如果锁还在
if (c == 0) {
// 设置锁的状态
if (compareAndSetState(0, acquires)) {
// 设置当前线程为锁的独占线程
setExclusiveOwnerThread(current);
return true;
}
}
// 如果锁的独占线程是当前线程
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
//设置锁的状态
setState(nextc);
return true;
}
return false;
}
锁的释放
如果该锁获取了n次,那么当前(n-1)次tryRelease方法返回false,而之后全部释放了,才会返回true。
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
公平锁和非公平锁的区别
公平性与否是针对锁的获取而言的,如果一个锁是公平的,那么锁的获取顺序应该符合请求的绝对次序,也就是FIFO。
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 查看是否有后继节点,如果没有才获取锁
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
欢迎关注公众号“程序员ZZ的源码”,一起来学习