Java并发之lock
相比于synchronized关键字,lock接口没有了隐式获取释放锁的便捷,但拥有了锁获取和释放的可操作性。lock接口是面向使用者的,定义了使用者和锁交互的接口隐藏了实现细节,而大多数锁的实现是通过聚合一个线程同步器子类来完成线程访问控制的,同步状态管理、线程排队、等待与唤醒等操作交给同步器来实现。
队列同步器
队列同步器AbstractQueuedSynchronizer,是用来构建锁和其他同步组件的基础框架,它使用一个int成员来表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。其设计是基于模板方法模式,使用者需要继承同步器并重写指定的方法来完成个性化需求。
- getState()获取当前的同步状态
- setState()设置当前的同步状态
- compareAndSetState(int expect,int update)使用CAS设置当前状态,具备原子性
AbstractQueuedSynchronizer的acquire方法分析:
public final void acquire(int arg) {
//调用自定义方法尝试修改同步器状态,允许失败
if (!tryAcquire(arg) &&
//如果失败调用addWaiter方法将节点添加到队列尾部
//然后调用acquireQueued方法使节点进行自旋,死循环不断进行状态获取
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
//当前线程中止
selfInterrupt();
}
//添加节点到链表对类尾部,然后tail节点
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
ReentrantLock锁实现示例
内部实现了Sync、NoFairSync、FairSync多个内部类,通过继承同步器来实现了公平锁和非公平锁。
abstract static class Sync extends AbstractQueuedSynchronizer {
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//如果当前状态为0,可以尝试获取锁
if (c == 0) {
if (compareAndSetState(0, acquires)) {
//设置当前占有锁的线程
setExclusiveOwnerThread(current);
return true;
}
}
//如果当前锁状态不为0,但是是当前线程在占有锁,仍可以尝试获取锁
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;
}
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;
}
//其余方法省略。。。
}
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);
}
}
相比非公平锁,公平锁的实现过程中只需要调用!hasQueuedPredecessors()对当前节点是否首节点进行判断即可,在Lock接口实现中我们直接调用上面实现的方法。
public void lock() {
sync.lock();
}
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
public void unlock() {
sync.release(1);
}

浙公网安备 33010602011771号