对于ReentrantLock,一般我们在调用无参构造函数的时候,构造的是非公平锁,当前类也存在一种可以指定锁类型的构造方法,即 ReentrantLock(boolean fair),ReentrantLock锁的实现是通过内部类FairSync和NonfairSync继承AQS实现的。
我们今天主要讨论下这两个内部类,从而探讨下代码级别是如何实现公平锁和非公平锁的。
先看ReentrantLock加锁方法,可以自己去看源码,底层是在FairSync和NonfairSync这两个内部里面做的逻辑
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
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;
}
}
不同的是,非公平锁在lock时,先调用底层的unsafe原生类的CAS方法,获取当前锁的机会,如果获取不成功则和公平锁一样调用acquire(1);
我们再来看acquire(1)方法,在AQS中实现如下:
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
会先执行tryAcquire方法,然后根据短路与看时候需要进行acquireQueued,acquireQueued方法是指当前线程未获得锁的情况下,将该线程加入等待的引用链中
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;
}
贴上公平锁的tryAcquire方法实现
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;
}
贴上非公平锁的tryAcquire方法实现
比较关键的差别是在hasQueuedPredecessors方法上,非公平锁不会调用该方法,公平锁中该方法的意思是检测当前线程是否为acquireQueued方法往head之后添加引用,如果是则利用CAS方法获得当前reentrantLock。
其实公平锁和非公平锁最大的差别就是在获取锁时,是否会去找当前头结点之后维护的等待队列。
分享到:
相关推荐
公平锁和非公平锁是ReentrantLock的两种模式。公平锁是指锁的获取顺序是按照线程的请求顺序,非公平锁是指锁的获取顺序是按照线程的请求顺序,但可以插队。ReentrantLock默认是非公平锁,可以通过构造方法指定使用...
总的来说,这段代码展示了`ReentrantLock`的公平和非公平锁的使用,并通过`CountDownLatch`进行多线程同步。了解这两种锁的区别和应用场景对于优化并发程序的性能和线程调度非常重要。在实际开发中,应根据具体需求...
"公平锁&非公平锁" 公平锁(Fair Lock)和非...公平锁和非公平锁都是 ReentrantLock 的实现方式,前者能够避免饥饿现象的发生,而后者可能会导致饥饿现象的发生。开发者可以根据实际情况选择使用公平锁或非公平锁。
ReentrantLock是由Java提供的可重入互斥锁,支持公平锁和非公平锁两种模式。非公平锁的特性是获取锁的线程不论先后,都有机会获得锁,而公平锁则遵循先进先出的原则,保证线程按照请求锁的顺序进行。 2. **...
下面是一个简单的ReentrantLock公平锁与非公平锁的使用示例: ```java import java.util.concurrent.locks.ReentrantLock; public class LockDemo { private ReentrantLock fairLock = new ReentrantLock(true); ...
Java线程公平锁和非公平锁是Java并发编程中重要的概念,主要体现在`java.util.concurrent.locks`包下的`ReentrantLock`类中。`ReentrantLock`提供了可配置的公平性和非公平性,允许开发者根据应用需求选择合适的锁...
其中,fair参数表示是否使用公平锁,如果为true,则使用公平锁,否则使用非公平锁。 ReentrantLock的锁机制 ReentrantLock的锁机制是通过CAS(Compare-And-Swap)操作来实现的。CAS操作是原子操作,用于更新对象内...
FairSync和NonfairSync则分别实现了公平锁和非公平锁的逻辑。在FairSync中,获取锁时会检查队列中是否有其他线程等待,确保按照等待顺序进行;而在NonfairSync中,线程获取锁时会尝试直接通过CAS操作获取,即使这...
ReentrantLock 的构造方法可以指定锁的类型,包括公平锁和非公平锁。公平锁通过公平的机制来分配锁,确保每个线程都能公平地获取锁,而非公平锁则不保证锁的公平性。默认情况下,ReentrantLock 使用非公平锁,它的...
ReentrantLock允许显式获取和释放锁,并且支持更丰富的锁原语,如公平锁、非公平锁、可中断锁、定时锁等。通过lock()和unlock()方法,程序员可以更好地控制锁的生命周期。此外,ReentrantLock还支持锁的条件条件...
此外,ReentrantLock还支持公平锁和非公平锁两种模式。公平锁按照线程在等待队列中的顺序获取锁,而非公平锁则不保证公平性,可能会让等待时间较短的线程优先获取锁。这可以通过构造函数传入的boolean参数来选择,...
ReentrantLock的内部类Sync继承自AQS,进一步分为FairSync(公平锁)和NonfairSync(非公平锁)两个子类。公平锁确保线程按照它们请求锁的顺序获取锁,而非公平锁则不保证这种顺序,可能会有线程插队获取锁。 **...
5. 公平锁和非公平锁的实现,公平锁遵循FIFO原则,而非公平锁则更注重效率。 通过对`ReentrantLock`的深入理解,开发者可以更好地设计和实现高效的并发程序,灵活地控制锁的获取和释放,以及处理线程的中断和同步...
- 它支持公平和非公平两种获取锁的策略,默认为非公平锁。 2. **重要特性**: - **可中断等待**:通过`lock.tryLock()`和`lock.tryLock(long timeout, TimeUnit unit)`方法,可以在等待获取锁时响应中断。 - **...
1. ReentrantLock的介绍 ...与此同时,ReentrantLock还支持公平锁和非公平锁两种方式。 那么,要想完完全全的弄懂ReentrantLock的话,主要也就是ReentrantLock同步语义的学习:1. 重入性的实现原理;2. 公平
- `ReentrantLock(boolean fair)`:创建公平锁或非公平锁,取决于`fair`参数。 - `getHoldCount()`:返回当前线程持锁的次数。 - `getOwner()`:返回当前持有锁的线程,如果没有线程持有,则返回`null`。 - `...
尽管如此,ReentrantLock仍然有其独特之处,比如它可以提供公平锁和非公平锁的选择,支持中断锁等待,以及更细粒度的控制线程间的唤醒与等待。 1. **Lock接口**: - `lock()`:获取锁,如果无法立即获取,线程会被...
- 支持公平锁(通过构造函数传入`true`)和非公平锁(默认)。 3. **高级功能**: - 可以尝试获取锁:`tryLock()`方法可以在无法立即获取锁时返回,避免了不必要的等待。 - 可中断锁:通过`lockInterruptibly()`...
ReentrantLock中的Sync类是AQS的子类,分为公平锁FairSync和非公平锁NoFairSync。公平锁遵循先来先服务的原则,而非公平锁允许线程抢占锁。 2. **锁的状态** AQS中使用一个int类型的state变量表示锁的状态,state...
- `ReentrantLock`提供了公平锁和非公平锁的选择。公平锁确保线程按等待顺序获取锁,而非公平锁则可能导致线程插队。`synchronized`默认是非公平的,且不支持公平模式。 - `ReentrantLock`支持定时和轮询尝试获取...