当然,我很愿意为您讲解《Java并发系列之ReentrantLock源码分析》的完整攻略。
Java并发系列之ReentrantLock源码分析
一、ReentrantLock概述
ReentrantLock是Java提供的一种基于互斥锁的同步机制,它比synchronized更加灵活和强大,能够支持更复杂的同步需求。在Java并发编程中,ReentrantLock常被用来代替synchronized,以实现更细粒度的线程控制。
ReentrantLock实现了Lock接口,提供了与synchronized类似的功能,但在性能、自定义锁定机制、公平/非公平性等方面更加优秀。
二、ReentrantLock的源码分析
2.1 构造函数
ReentrantLock有以下两个构造函数:
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
这两个构造函数都会初始化一个Sync类型的sync对象,Sync类型是ReentrantLock内部的一个抽象类,而NonfairSync和FairSync则是Sync的两个实现类,分别对应“非公平锁”和“公平锁”。
2.2 Lock/Unlock
ReentrantLock提供了两个基本的操作:lock()和unlock()。
lock()方法的实现如下:
public void lock() {
sync.lock();
}
这里调用了Sync类型对象的lock()方法。
unlock()方法的实现如下:
public void unlock() {
sync.unlock();
}
同样,这里也调用了Sync类型对象的unlock()方法。
2.3 Sync类
Sync类是ReentrantLock内部的一个抽象类,它提供了lock()、tryLock()和unlock()等方法的基本实现。
abstract static class Sync extends AbstractQueuedSynchronizer {
// ...
}
Sync继承了AbstractQueuedSynchronizer(AQS)类,AQS是Java并发包中比较复杂的一个类,它提供了一套基于CAS的线程同步机制。Sync通过继承AQS并实现其中的方法,来实现Lock接口的功能。
2.4 NonfairSync类和FairSync类
NonfairSync和FairSync是Sync的两个实现类,分别对应非公平锁和公平锁。
它们的区别在于,在获取锁的时候,公平锁会优先考虑等待时间较长的线程,而非公平锁则是直接尝试获取锁,如果获取失败再进入等待队列。
NonfairSync实现了Sync的lock()和tryAcquire(int acquires)方法:
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
公平锁FairSync实现了Sync的tryAcquire(int acquires)和tryAcquireNanos(int acquires, long nanosTimeout)方法:
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;
}
protected final boolean tryAcquireNanos(int acquires, long nanosTimeout)
throws InterruptedException {
if (nanosTimeout <= 0L)
return false;
final long deadline = System.nanoTime() + nanosTimeout;
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;
}
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout > 0L) {
Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
Node p = node.predecessor();
if (p == head &&
tryAcquire(acquires)) {
setHead(node);
p.next = null; // help GC
failed = false;
return true;
}
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L) {
break;
}
LockSupport.parkNanos(this, nanosTimeout);
}
} finally {
if (failed)
cancelAcquire(node);
}
}
return false;
}
2.5 ReentrantLock示例说明
下面是两个使用ReentrantLock的示例。
第一个示例展示了如何使用ReentrantLock来实现生产者-消费者的问题。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ProducerConsumer {
private static final int BUFFER_SIZE = 10;
private final int[] buffer = new int[BUFFER_SIZE];
private int index, count;
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
public void produce(int num) throws InterruptedException {
lock.lock();
try {
while (count == buffer.length) {
notFull.await();
}
buffer[index++] = num;
if (index == buffer.length) {
index = 0;
}
count++;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public int consume() throws InterruptedException {
lock.lock();
try {
while (count == 0) {
notEmpty.await();
}
int result = buffer[--index];
if (index < 0) {
index = buffer.length - 1;
}
count--;
notFull.signal();
return result;
} finally {
lock.unlock();
}
}
}
第二个示例展示了如何使用ReentrantLock来实现读写锁。
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockDemo {
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void read() {
lock.readLock().lock();
try {
// 读取数据
} finally {
lock.readLock().unlock();
}
}
public void write() {
lock.writeLock().lock();
try {
// 写入数据
} finally {
lock.writeLock().unlock();
}
}
}
以上就是Java并发系列之ReentrantLock源码分析的完整攻略,希望对您有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发系列之ReentrantLock源码分析 - Python技术站