1、基础使用
//声明锁,默认为true非公平锁
static Lock lock1=new ReentrantLock();
public static void main(String[] args) {
try{
lock1.lock();
// todo
}catch (Exception e){
e.printStackTrace();
}finally {
lock1.unlock();
}
}
2、非公平锁源码追踪
2.1 非公平锁加锁lock()
final void lock() {
//(1)首先通过cas设置state变量值,如果设置成功则返回
if (compareAndSetState(0, 1))
//设置当前线程为占有锁的线程
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
public final void acquire(int arg) {
//!tryAcquire(arg) 如果获取锁失败则执行acquireQueued(addWaiter(Node.EXCLUSIVE), arg),将当前线程放入队列并自旋等待
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//再次判断锁是否空闲
if (c == 0) {
//这个地方与公平锁不同的时直接设置state标识,不在判断aqs是否为空
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//判断获取锁的线程是否是当前线程
else if (current == getExclusiveOwnerThread()) {
//重入次数加1
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
//将线程加入队列
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
//获取尾节点,判断是否是空节点,如果是空节点则初始化节点enq(node)
Node pred = tail;
if (pred != null) {
//将当前节点的prev指针指向尾节点
node.prev = pred;
//通过CAS将当前节点设置为tail节点
if (compareAndSetTail(pred, node)) {
//将前面节点的next指针指向当前节点
pred.next = node;
return node;
}
}
//初始化节点
enq(node);
return node;
}
//这里采用自旋操作,避免节点初始化失败导致AQS队列异常
private Node enq(final Node node) {
for (;;) {
//获取尾节点
Node t = tail;
if (t == null) { // Must initialize
//如果尾节点为空,通过CAS初始化head节点
if (compareAndSetHead(new Node()))
//将尾节点同时指向头节点所在的节点
tail = head;
} else {
//将当前节点的prev指针指向节点t
node.prev = t;
//通过CAS将当前节点设为tail节点
if (compareAndSetTail(t, node)) {
//将节点t的next指针指向当前节点
t.next = node;
return t;
}
}
}
}
//自旋锁和阻塞操作
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
//获取当前节点的prev指向的节点
final Node p = node.predecessor();
//如果当前节点的prev指向head节点,尝试竞争锁
//这个地方判断节点是否是第一个节点
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);
}
}
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
//修改state标记,当值为0返回true
if (tryRelease(arg)) {
Node h = head;
//waitStatus初始化状态为0
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
//重入次数减1
int c = getState() - releases;
//如果当前线程不是锁持有线程抛异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
//如果state为0则清空当前持锁线程(重入次数为0)
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
//修改state值
setState(c);
return free;
}
private void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
Node s = node.next;
//如果head节点后面的节点为空或者线程已经取消,则将对应的节点移除
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
//如果head后面的节点不为空,则唤醒对应节点的线程
if (s != null)
LockSupport.unpark(s.thread);
}
关键变量描述
类型 | 属性名 | 描述 |
---|---|---|
int | waitStatus | 等待状态 |
Node | prev | 指向队列的前一个 |
Node | next | 指向队列中后一个节点 |
Thread | thread | Node的持有线程 |
Node | nextWaiter | 下一个等待condition的Node |
没有回复内容