什么是AQS(全称AbstractQueuedSynchronizer)
代表:重入锁、独占锁/共享锁、公平锁/非公平锁
是JUC包中线程阻塞、阻塞队列、唤醒、尝试获取锁的一个框架
AbstractQueuedSynchronizer是全称,是一个模板模式,一些线程同步公共的抽象类,里面有同步线程的类公共行为,比如:阻塞队列、加锁
AQS主要思想
尝试获取锁,如果获取失败就加入阻塞队列,如果有条件就先加入条件队列(如:ReentrantLock的创建多个newCondition()),条件队列中线程达到某个条件就会加入到阻塞队列,阻塞队列中的线程一直尝试获取锁。
ReentrantLock lock = new ReentrantLock(); 其中有个参数是否为公平锁
加锁
1. 判断参数是否为true 如果为true那么参数Syn就是FairSync,如果为false或者空代表非公平锁 Syn就是NonfairSync
2. 使用lock.lock();
公平锁:直接加入等待队列
非公平锁:尝试获取锁,如果获取到了那么就改变锁状态为1代表已经有线程持有锁了并且将当前线程复制给exclusiveOwnerThread参数留作后面判断是否为当前线程,如果当前线程就可以冲入直接返回true拿到锁,如果获取锁失败了就加入等待队列,加入等待队列时还会再次获取一次锁,如果还是失败了就会彻底加入等待队列
3. 加入等待队列
加入阻塞队列时再次尝试获取锁
队列使用的是链表,将当前Node节点加入到链表后面,如果是第一次加入到链表中就会创建头节点,头节点代表的就是已经获取到锁的那个线程,Thread参数为null,当前线程的Node节点在这个节点的后面并且Thread为当前线程。
如果第一次加入阻塞队列,初始化队列,下边这个代码相当于是自旋锁循环设置头节点
设置当前ReentrantLock的wait状态为-1。
加入队列以后设置指定当前线程 阻塞使用 LockSupport.park(this);
当前线程调用interrupted();方法优雅停止线程。
加锁完毕
释放锁
如果当前操作的线程不是加锁的线程就会抛出 IllegalMonitorStateException异常;
尝试改变当前锁的状态为0,如果成功就将当前操作线程改为0并且状态改为0
修改waitStauts并且指定出队的线程唤醒。