1、AQS:AbstractQueuedSynchronizer,抽象队列同步器。是java自带除synchronized关键字外的锁机制
2、是用来构建锁及其他同步器的重要框架,通过内置的CLH队列来完成资源获取线程的排队工作,将每条要去获取资源的线程分装成Node节点来实现锁的分配,有一个int变量来表示
锁的持有状态(private volatile int state),通过cas来操作state完成状态修改(0-空闲;1-阻塞)
3、ReentrantLock节点AQS
3.1、state有三个值:0-空闲;1-阻塞;大于1可重入
3.2、n个线程进入,CLH队列中会有n+1个node节点,队列第一个是哨兵节点
3.3、公平锁和非公平锁
区别:
公平锁每个线程进来会先判断当前自己是否位于队列首位,如果是则尝试获取锁(cas操作state),否则加入队列
非公平锁新线程进来会先尝试获取锁(cas操作state)如果成功则将自己设置为第一个否则加入队列,可能导致有的线程长时间执行不到。
ReentrantLock默认创建的是非公平锁
ReentrantLock lock = new ReentrantLock(true) 创建的是公平锁。
公平锁和非公平锁区别代码就在于公平锁多了65行!hasQueuedPredecessor(),此方法用于公平锁加锁时判断等待队列中是否存在有效节点
非公平锁:
36行:cas操作state,如成功则说明空闲,设置state为1,队列第一个设置为当前线程
39行:如有阻塞,则调用acquire(1)
83行:调用tryAcquire(),当前为非公平锁即调用42行->5行
7行:获取state
9行:如果cas操作state成功,则设置state为1,队列第一个设置为当前线程
14行:如果当前线程又进来,则设置state=state+1(即可重入)
84行:如果调用tryAcquire()失败即没有取到锁,则先调用addWaiter将当前线程封装成Node加入CLH链表,acquireQueued()
1 /** 2 * Performs non-fair tryLock. tryAcquire is implemented in 3 * subclasses, but both need nonfair try for trylock method. 4 */ 5 final boolean nonfairTryAcquire(int acquires) { 6 final Thread current = Thread.currentThread(); 7 int c = getState(); 8 if (c == 0) { 9 if (compareAndSetState(0, acquires)) { 10 setExclusiveOwnerThread(current); 11 return true; 12 } 13 } 14 else if (current == getExclusiveOwnerThread()) { 15 int nextc = c + acquires; 16 if (nextc < 0) // overflow 17 throw new Error("Maximum lock count exceeded"); 18 setState(nextc); 19 return true; 20 } 21 return false; 22 } 23 24 25 /** 26 * Sync object for non-fair locks 27 */ 28 static final class NonfairSync extends Sync { 29 private static final long serialVersionUID = 7316153563782823691L; 30 31 /** 32 * Performs lock. Try immediate barge, backing up to normal 33 * acquire on failure. 34 */ 35 final void lock() { 36 if (compareAndSetState(0, 1)) 37 setExclusiveOwnerThread(Thread.currentThread()); 38 else 39 acquire(1); 40 } 41 42 protected final boolean tryAcquire(int acquires) { 43 return nonfairTryAcquire(acquires); 44 } 45 } 46 47 /** 48 * Sync object for fair locks 49 */ 50 static final class FairSync extends Sync { 51 private static final long serialVersionUID = -3000897897090466540L; 52 53 final void lock() { 54 acquire(1); 55 } 56 57 /** 58 * Fair version of tryAcquire. Don‘t grant access unless 59 * recursive call or no waiters or is first. 60 */ 61 protected final boolean tryAcquire(int acquires) { 62 final Thread current = Thread.currentThread(); 63 int c = getState(); 64 if (c == 0) { 65 if (!hasQueuedPredecessors() && 66 compareAndSetState(0, acquires)) { 67 setExclusiveOwnerThread(current); 68 return true; 69 } 70 } 71 else if (current == getExclusiveOwnerThread()) { 72 int nextc = c + acquires; 73 if (nextc < 0) 74 throw new Error("Maximum lock count exceeded"); 75 setState(nextc); 76 return true; 77 } 78 return false; 79 } 80 } 81 82 public final void acquire(int arg) { 83 if (!tryAcquire(arg) && 84 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) 85 selfInterrupt(); 86 }