以非公平锁为例子:
package com.jmdf.redis.project.aqs;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestAQS {
private static Lock lock = new ReentrantLock();
public static void main(String[] args) {
Thread[] threads = new Thread[3];
for (int i = 0;i<threads.length;i++) {
threads[i] = new Thread(()->{
lock.lock(); //①→加锁
try { Thread.sleep(Integer.MAX_VALUE); }catch(Exception e){ }
finally {
lock.unlock(); ②→//解锁
}
},"Thread"+i);
}
for (Thread thread :threads) thread.start();
for (Thread thread :threads) try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); }
}
}
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1)) //unsafe.compareAndSwapInt(this, stateOffset, expect, update);
setExclusiveOwnerThread(Thread.currentThread()); //当前锁的所有权线程
//if段操作后面还有,前面重复为了提高性能。
else
acquire(1); //获取锁失败→
}
/**
* 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) && //①→尝试获取锁
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))//addWaiter(Node.EXCLUSIVE)尝试获取锁失败,自旋CAS加入CHL队列,acquireQueued 方法 自旋尝试获取锁
selfInterrupt(); //中断
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
/**
* 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(); //volatile修饰的int变量
if (c == 0) { //前面的线程获取锁,完成业务后,占用的锁释放了
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) { //state !=0,当前线程等于Lock实现类锁所有权线程,则为可重入锁,不需要获取锁,只需要state++;
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false; //当前线程尝试获取锁失败。
}
/**
* 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) {
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;
}
/ * if there is a queued thread preceding the
* current thread, and {@code false} if the current thread
* is at the head of the queue or the queue is empty
* @since 1.7
* 公平锁判断队列为空才去尝试获取锁,高并发情况下并非绝对公平
*/
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order 尾节点
Node h = head; //头节点
Node s;
return h != t && //h!=t 为false==→空队列,后面判断是为了防止并发
((s = h.next) == null || s.thread != Thread.currentThread());
}
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node())) //延迟初始化队列节点 在AQ类加载时声明了成员节点,static{}获取了head、tail、pre、next在jvm里的位置的偏移量,为以后cas做准备
tail = head; //头尾节点相等,队列初始化结束,队列为空
} else {
node.prev = t; // tail ←prev node
if (compareAndSetTail(t, node)) {//若队列不为空,尾节点指针指向当前节点的前置节点,cas 把当前node.next =null 尾节点cas成功! node next→null
t.next = node; // tail next→node
return t;
}
}
}
}
/**
* Acquires in exclusive uninterruptible mode for thread already in
* queue. Used by condition wait methods as well as acquire.
*
* @param node the node
* @param arg the acquire argument
* @return {@code true} if interrupted while waiting
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();//node 节点的前置节点
if (p == head && tryAcquire(arg)) { //如果前置节点为head ,则可以尝试获取锁
setHead(node); //把该节点设置为head节点
p.next = null; // help GC 释放 node节点的前置节点,从队列中清除
failed = false;
return interrupted; //false
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}