Lock接口
1.实现原理
AQS,队列同步器。通过volitile变量state和CAS实现的一个双端队列,子类需要重写tryAcquire方法
AQS获取锁的步骤
- A尝试获取锁
- 如果失败,则将A封装成一个Node,尝试通过CAS将其放入队列尾部
- 放入队列尾部的时候也去尝试获取锁,如果还没有成功,加入队列尾部。
- 如果该节点的pre是头节点,则其自旋,不断的去获取锁;
- 如果pre不是头结点,则通过LockSupport.park() 方法将其阻塞
2.RetreentLock
可重入锁,实现了FairLock和UnFairLock,默认是UnFairLock;
公平锁的获取,先看有没有线程占有锁。AQS队列自旋的时候要去看pre节点是不是头结点;如果是头结点,看获取锁的是否是当前线程,如果是,则获取锁,如果不是,获取失败。
非公平锁不会去看头节点是否是头结点。先看有没有线程获取锁,在看获取锁的是不是当前线程。
非公平锁效率高,可重入锁效率高
3.ReentrantReadWriteLock
读写锁氛围读锁和写锁。
3.1实现
一个32位的数字,高16位是写锁,低16位是读锁
3.2 写锁
写锁是独占式的可重入锁,
当一个线程获取锁,如果有读锁或者写锁占用着,则获取失败;
3.3读锁
读锁时可以共享的可重入锁,
当一个线程A获取读锁,
如果当前其他线程B占用着写锁,则,获取失败;如果B占用读锁,则获取成功;
如果当前线程占用写锁,也能获取成功;
3.4锁降级
是指一个线程将当前的写锁降级成读锁,但是不支持升级;
降级的过程: 获取写锁---获取读锁---释放写锁;
不是在释放写锁之后获取读锁,是因为防止其他线程获取资源的锁后,修改了资源,该线程发生了幻读。
4.Condition对象
每一个Lock中都有一个ConditionObject对象,其实是封装在AQS里面。SYNC继承了AQS,FairSYNC和UnFairSYNC都继承了SYNC,SYNC,FairSYNC和UnFairSYNC都是RetreentLock的内部类。
获取Condition必须之前获取了锁,每一个Condition有自己的等待队列,当调用LockSupport.park()进入等待队列,LockSupport.unpark()从等待队列中出来,进入AQS的同步队列。