当前位置: 代码迷 >> 综合 >> 并发-ReentrantLock
  详细解决方案

并发-ReentrantLock

热度:9   发布时间:2024-03-07 04:21:41.0

1. 背景

2. 介绍

可重入锁ReentrantLock,支持可重入的锁。表示同一个线程可对资源重复加锁。

2.1 特性

  • 支持公平锁和非公平锁,默认是非公平锁。公平锁的存在是减少“饥饿”发生的概率,等待越久的请求优先满足;

3. 源码

3.1 线程如何重复获取锁及最终的释放(以非公平锁为例)

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) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;
}

3.2  线程如何保证锁的最终释放(以非公平锁为例)

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;
}

3.3 公平锁如何实现

(1) 

protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {// 加入了同步队列中,当前节点是否有前驱节点,有就返回true,代表有线程比当前线程更早地请求获取锁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;
}

(2)

  • 当队列只有一个节点或者无节点时,无需排队,返回false (第一个节点是不参与排队的,它本身是持有同步状态的)
  • 第二个节点是当前线程本身,返回false
public final boolean hasQueuedPredecessors() {// The correctness of this depends on head being initialized// before tail and on head.next being accurate if the current// thread is first in queue.Node t = tail; // Read fields in reverse initialization orderNode h = head;Node s;return h != t &&((s = h.next) == null || s.thread != Thread.currentThread());
}

 

4. 实战

5. FAQ

5.1 同步队列中不是每个节点都有机会争抢到CPU资源吗?

 

6. 参考资料