Lock:位于Java concurrent包中,常见的使用方式
Lock lock = new ReentrantLock();
try{
lock.lock();
...
}finally{
lock.unlock();//需要释放锁
}
Lock接口的方法:
/**
尝试获取锁。当该函数返回时,处于已经获取锁的状态。如果当前有别的线程获取了锁,则休眠。
*/
void lock();
/**
尝试获取锁。如果有别的线程获取了锁,则休眠。当该函数返回时,有两种可能:
a.已经获取了锁
b.获取锁不成功,但是别的线程打断了它。则该线程会抛出IterruptedException异常而返回,同时该线程的中断标志会被清除。
*/
void lockInterruptibly() throws InterruptedException;
/**
尝试获取锁并且立即返回true或者false。
*/
boolean tryLock();
/**
尝试获取锁。如果获取了锁,则返回true;如果没有获取锁,则等待预定的时间,若还无法获取锁,则返回false。
*/
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
/**
释放锁
*/
void unlock();
/**
给锁创建一个ConditionObject对象,Condition的await()方法能让当前线程释放锁,并让线程处于阻塞状态;signal()方法是唤醒其他阻塞线程。
*/
Condition newCondition();
Lock接口的实现类
Lock的实现类:ReentrantLock(排他锁)、WriteLock(排他锁)、ReadLock(共享锁)
ReentrantLock的实现原理
- 构造函数
/**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() {
//默认是非公平锁
sync = new NonfairSync();
}
/**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
- Lock
/**
* Sync object for non-fair locks
*/
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))
//直接拿到锁,将这个线程设为sync的独有者。
setExclusiveOwnerThread(Thread.currentThread());
else
//排队获取锁
acquire(1);
}
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;
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) {
// 公平锁,检查该线程是否在queue首位
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//该线程之前已经获取了锁,状态+1 (重入锁)
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
/**
* Acquires in exclusive mode, ignoring interrupts. Implemented
* by invoking at least once {@link #tryAcquire},
* returning on success. Otherwise the thread is queued, possibly
* repeatedly blocking and unblocking, invoking {@link
* #tryAcquire} until success. This method can be used
* to implement method {@link Lock#lock}.
*
* @param arg the acquire argument. This value is conveyed to
* {@link #tryAcquire} but is otherwise uninterpreted and
* can represent anything you like.
*/
public final void acquire(int arg) {
// 尝试获取锁,成功则返回
if (!tryAcquire(arg) &&
// 1. addWaiter()将该线程加入queue的尾部
// 2. acquireQueued()判断该线程是否在队首
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
// 获取锁成功才会返回。
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);
}
}
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
//非公平锁,直接去尝试获取锁,并不检查该线程是否在queue首位
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;
}
- unlock()
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
//尝试释放锁
if (tryRelease(arg)) {
Node h = head;
//从头节点往队尾找到第一个没有被取消的线程节点,唤醒它。
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}