目录
1. 作用
ReentrantLock基于AQS,在并发编程中它可以实现公平锁和非公平锁来对共享资源进行同步。
同时,和synchronized一样,ReentrantLock支持可重入,除此之外,ReentrantLock在调度上更灵活,支持更多丰富的功能。
2. Lock
ReentrantLock 实现了Lock接口。
Lock的意义在于提供了区别于synchronized的另一个具有更多广泛操作的同步方式,他能支持更多灵活的结构,并且可以关联多个Condition对象。
package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
public interface Lock {
// 用于获取锁
void lock();
// 假设当前线程在等待锁,如果被中断,则会抛出中断异常
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
// 新建一个绑定在当前lock上的condition对象
Condition newCondition();
}
2.2 condition对象
表示一种等待状态。
比如获取锁的线程需要满足某些条件才能继续执行,那么他可以通过awit方法,注册在condition对象上进行等待,然后通过condition对象中的signal将其唤醒
一个lock上可以关联多个condition,多个线程可以被绑定在不同的condition上,这样就可以分组唤醒。
condition还实现了限时、中断相关功能,丰富了线程调度策略。
3. ReentrantLock
public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;
/** Synchronizer providing all implementation mechanics */
// 被final修饰,说明一旦被初始化就不可以被修改其引用的地址了
private final Sync sync;
/**
* Base of synchronization control for this lock. Subclassed
* into fair and nonfair versions below. Uses AQS state to
* represent the number of holds on the lock.
*/
abstract static class Sync extends AbstractQueuedSynchronizer {...}
/**
* Sync object for non-fair locks
*/
static final class NonfairSync extends Sync {...}
/**
* Sync object for fair locks
*/
static final class FairSync extends Sync {...}
}
3.1 Sync 对象
/**
* Base of synchronization control for this lock. Subclassed
* into fair and nonfair versions below. Uses AQS state to
* represent the number of holds on the lock.
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
* 非公平的尝试获取锁
*/
@ReservedStackAccess
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState(); // 获取aqs中的锁状态
if (c == 0) { // 锁空闲
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 判断是否独占锁的线程是不是自己;如果不是,返回false,获取锁失败
// 如果是自己获取了锁,那么实现可重入机制,并累计重入的次数
// 因为释放时也需要释放相同的次数
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;
}
// 返回值的true和false,代表是否被完全释放,而不是成功释放
@ReservedStackAccess
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;
}
protected final boolean isHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
// Methods relayed from outer class
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
final boolean isLocked() {
return getState() != 0;
}
/**
* Reconstitutes the instance from a stream (that is, deserializes it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
3.1.1 可重入以及可重入锁的概念
可重入——单个线程执行时, 重新进入同一个子程序, 仍然是线程安全的. 。
可重入锁——即一个线程无需释放,而可以重复的获取锁n次;在释放时,也需要释放n次
3.1.2 公平锁、非公平锁
公平锁——按照请求锁的顺序分配;拥有稳定获得锁的机会;但是性能可能比非公平锁低
非公平锁——不按照请求锁的顺序分配;不一定拥有获得锁的机会;但是性能可能比公平锁高(因为线程的唤醒需要一定的时间,这段时间完全可以被抢占去利用)
/**
* Sync object for non-fair locks
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
/**
* Sync object for fair locks
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
@ReservedStackAccess
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;
}
}
4、java中断机制