AQS: AQS是基于先进先出(FIFO)的等待队列来实现锁的同步器, AQS定义了一个state变量, 必须原子性的修改这个变量
ReentrantLock公平锁和非公平锁
公平锁: 线程获取锁的顺序是按照线程访问锁的先后顺序获取的,最前面的线程总是最先获取到锁
非公平锁: 线程获取锁的顺序是随机的,并不会遵循先来先得的规则,所有线程会竞争获取锁
不公平的地方体现
这个lock的时候, 非公平锁使用compareAndSetState(0,1)方法来判断是否能修改seate的值, 能修 改就会占用锁, 其他没获取到锁的线程就会进入队列等待
公平锁则没有实现, 那个线程先来访问即可先获取到锁
state变量在ReentrantLock中的含义
1. state == 0 : 表示当前没有线程持有锁
2. state != 0 : 表示有线程持有锁了
state从 0 -> 1 就是线程持有锁的过程
当已经持有锁的线程重新获取锁时, state的值就会 + 1 (重入)
acquire(1)方法:
1. 尝试加锁
2. 如果抢占锁失败, 把自己加入到队列中
3. 在队列中等待, 伺机抢锁
tryAcquire(arg)方法:
1. 获取state的值
2. 判断state的值 :
当state == 0 , 当前没有人持有锁, 判断队列中有没有排队的线程, 没人即可尝试抢占锁, 抢占到了设置标记
setExclusiveOwnerThread(current);
当state != 0, 先判断当前线程是否和占有锁的线程是同一个, 如果是的话将 state + 1
addWaiter(Node mode)方法:
Node
head: 指向头节点的引用
tail: 指向尾节点的引用
当tail == null , 初始化队列会创建一个虚拟的头节点, 在下一次循环中把当前线程包装的Node对象的pred指向虚拟的头节点, 通过compareAndSetTail(t, node)方法抢占tail应用
当队列已经初始化过
将tail的引用指向, 当前线程node节点
当有新的线程来时:
acquireQueued(final Node node, int arg)方法
当发现自己的上一个节点是头节点时 ----> 尝试抢占锁
抢占成功 setHead(Node) 把自己设置成头节点 p.next ==null
抢占失败 shouldParkAfterFailedAcquire(p, node) 方法中断
unparkSuccessor(node) 唤醒
未完 暂时只学到这里, 有理解不好的地方 大家多多指正