Java 并发锁ReentrantLock的实现
全路径名:java.util.concurrent.locks.ReentrantLock 类定义如下:
/**
* @since 1.5
*/
public class ReentrantLock implements Lock, java.io.Serializable {
...
}
ReentrantLock 类实现了 Lock 接口,JDK1.5 引入。
ReentrantLock 使用上分公平锁和非公平锁,两种锁机制。默认无参构造方法 ReentrantLock() 创建的是非公平锁。可以使用有参构造函数 ReentrantLock(boolean fair) 选择使用公平锁,还是非公平锁。具体实现是通过 ReentrantLock 的内部类 FairSync 和 NonfairSync 来实现的。FairSync 和 NonfairSync 是 ReentrantLock 类中抽象内部类 Sync 的子类。具体源码如下:
public class ReentrantLock implements Lock, java.io.Serializable {
...
private final Sync sync;
...
abstract static class Sync extends AbstractQueuedSynchronizer {...}
static final class NonfairSync extends Sync {...}
static final class FairSync extends Sync {...}
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
public void lock() {
sync.lock();
}
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
public void unlock() {
sync.release(1);
}
public Condition newCondition() {
return sync.newCondition();
}
...
}java.util.concurrent.locks.Lock 接口定义了5个方法。具体源码如下:
public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}
通过对 ReentrantLock 类 Lock 接口 lock() 方法的实现, 来看 ReentrantLock 是如何实现公平锁的。
先说方式,再看源码更好理解一点。如果要公平,那就要有先来后到。就像超市购物结账一样:
- 如果结账时,恰好没有人,那就直接结账。直接就拿到了锁。
- 如果结账时,已经有人了,那就排到队伍的后面,等到你的时候才可以结账。也就是拿到了锁。
ReentrantLock 内部类 FairSync 负责实现公平锁机制,FairSync 类继承了 Sync 类,Sync类 继承了 AbstractQueuedSynchronizer 类。下面是与 lock() 方法有个的源码:
static final class FairSync extends Sync {
final void lock() {
acquire(1);
}
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;
}
}
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
...
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
...
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
...
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node)
&& parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
}
FairSync 的 lock() 方法调用 AbstractQueuedSynchronizer 类 acquire() 方法获取锁。AbstractQueuedSynchronizer 类 acquire() 方法中,先使用 FairSync 类的 tryAcquire() 方法实现没有人排队的场景。
- int c = getState(): 获取的是 AbstractQueuedSynchronizer 类的一个状态。c = 0 代表目前没有线程拿到这个锁
- !hasQueuedPredecessors(): 没有其他线程排队
- compareAndSetState(0, acquires):使用 CAS(Compare and Swap)CPU 硬件同步原语机制获取锁
- setExclusiveOwnerThread(current):如果成功拿到锁,将当前线程和锁绑定
- else if (current == getExclusiveOwnerThread()) 如果锁已经被当前线程绑定,状态 c 加 1。这块就体现了 ReentrantLock 可重入的概念。同一个线程未释放锁的情况下可以重复拿到锁,每次状态 c 加1。
AbstractQueuedSynchronizer 类 acquire() 方法中,如果没人排队的情况下,未能成功抢到锁。那就进入了排队的场景:
- for (;;) :无限循环
- if (p == head && tryAcquire(arg)):只有排队首的才有资格竞争锁。p 是获得锁的线程
- parkAndCheckInterrupt() 这个方法里实现的未获得锁的线程阻塞。这里不讨论。
看完 ReentrantLock 公平锁的实现,非公平锁的实现就简单了。非公平锁是通过 ReentrantLock 内部类 实现的,源码如下:
static final class NonfairSync extends Sync {
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
abstract static class Sync extends AbstractQueuedSynchronizer {
...
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;
}
...
}从源码看一看出,不排队,直接调用 compareAndSetState(0, 1) 方法抢。这就是非公平锁。
到此这篇关于Java 并发锁ReentrantLock的实现的文章就介绍到这了,更多相关Java 并发锁ReentrantLock内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
SpringCloud使用AOP统一处理Web请求日志实现步骤
这篇文章主要为大家介绍了SpringCloud使用AOP统一处理Web请求日志实现步骤,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-08-08
SpringCloud OpenFeign远程调用传递请求头信息方式
这篇文章主要介绍了SpringCloud OpenFeign远程调用传递请求头信息方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2026-03-03
SpringQuartz定时任务核心组件JobDetail与Trigger配置
Spring框架与Quartz调度器的集成提供了强大而灵活的定时任务解决方案,本文主要介绍了SpringQuartz定时任务核心组件JobDetail与Trigger配置,具有一定的参考价值,感兴趣的可以了解一下2025-04-04
Maven项目如何在pom文件中引入lib下的第三方jar包并打包进去
在使用Maven进行项目开发时,引入第三方私有的Jar包可能会遇到问题,一种常见的解决方案是将Jar包添加到项目的lib目录,并通过IDE进行配置,但这需要每个开发者单独操作,效率低下,更好的方法是通过Maven的pom.xml文件管理这些Jar包2024-09-09
SpringBoot整合Zookeeper实现分布式锁的具体步骤
在 Spring Boot 中实现分布式锁通常可以利用 ZooKeeper 来实现,以下是整合 Spring Boot 和 ZooKeeper 实现分布式锁的基本步骤,需要的朋友可以参考下2025-11-11
Java File类的简单使用教程(创建、删除、遍历与判断是否存在等)
这篇文章主要给大家介绍了关于Java File类的简单使用(创建、删除、遍历与判断是否存在等)的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-12-12


最新评论