您的位置:首页 > 其它

Lock

2017-08-14 00:00 92 查看
Lock相对于synchronized关键字的优势:

可以显式的加锁解锁,更有操作性

获取到锁的线程能够响应中断,当获取到锁的线程倍中断是,中断异常将会被抛出,勇士锁会被释放

超时获取锁,在指定的截止时间之前获取锁,如果截止时间到了仍旧无法获得锁,则返回

Lock的API:



队列同步器AbstractQueuedSynchronizer,使用来构建锁或者其他同步组件的基础框架,锁是面向使用者的。它定义了使用者与锁交互的接口,隐藏了实现细节;同步器面向的是锁的实现者,它简化了锁的实现方式,屏蔽了同步状态管理、线程的排队、等待与唤醒等底层操作。

同步器使用了模板方法模式,重新同步器指定的方法时,需要使用同步器提供的如下3个方法来访问或修改同步状态:

getState():获取当前同步状态

setState(int newState):设置当前同步状态

compareAndSetState(int expect, int update):使用CAS设置当前状态,该方法能够保证状态设置的原子性





同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态管理



同步队列准讯FIFO,首节点是获取同步状态成功的节点,首节点的线程在释放同步状态时,将会唤醒后续节点,而后续节点将会在获取同步状态成功时将自己设置为首节点,如下:



独占式同步状态获取流程,也就是acquire(int arg)方法调用流程,如下图:



独占获取锁的过程:

调用tryAcquire(int arg)这个方法的实现中公平锁和非公平锁有点区别,公平锁会判断队列是否为空,如果为空或者当前线程是首节点的下一个节点(正好在轮询CAS)这尝试CAS更改一次锁状态,如果失败进入下一步;

将当前线程封装成一个独占Node使用CAS自旋加入队列尾部,并且自旋抢夺锁,不过由于判断条件会判断当前节点是否为首节点的子节点,所以非第二个节点并不会真的发起CAS;

当前节点判断前一个节点为状态为0,会在设置状态为SIGNAL(-1),下一次循环当前一个节点为SIGNAL,当前线程陷入等待;

共享锁和独占锁的区别主要是锁状态的区别,独占锁状态只有0--空闲1--独占,共享锁可以>1,每次加锁数字加1,解锁-1,或者像Semaphore的实现,根据传入的许可证总数permits,每次加锁自减1,当值为0时,加锁失败,加入同步队列

独占超时同步状态获取流程,如下图:



ReentrantReadWriteLock:

锁状态设计很有意思使用一个int值,高16位表示读锁状态,低16位表示写锁状态。

写锁持有状态,除了持有锁的线程可以重入加写锁,或者加读锁,其他线程不能加锁。

读锁持有状态,其他线程可以加读锁不能加写锁。

LockSupport方法:



Condition方法:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Lock Concurrent