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的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方法:
相关文章推荐
- 计划翻译The Old New Thing上的LockWindowUpdate系列文章
- HDU 1195 Open the Lock (双宽搜索)
- 锁·二则——lock关键字详解 (转)
- 启动Linux上Weblogic Server报错: <BEA-141281> <unable to get file lock, will retry ...>
- 使用C# lock同时访问共享数据
- ReentrantReadWriteLock
- NET多线程同步方法详解(三):读写锁(ReadWriteLock)
- 无锁数据结构(Lock-Free Data Structures)
- c# 线程同步: 详解lock,monitor,同步事件和等待句柄以及mutex
- Java线程(6)锁对象Lock-同步问题更完美的处理方式
- ORACLE中的锁(LOCK)
- hdu 1195 Open the Lock(基础bfs)
- 说Hand-over-hand lock: 通读Concurrent Programming in Java: Design Principles and Patterns (1)
- 使用synchronized和Lock对象获取对象锁
- Lock obtain timed out: Lock@的解决方法(lucene)
- JAVA Lock 多线程顺序执行
- load,get;find,iterator;merge,saveOrUpdate,lock的区别
- hdu 1195 Open the Lock(bfs)
- MyEclipse部署文件被lock的问题
- java并发 lock锁