Java 5.0之前,在协调线程对共享数据的访问时可以使用的机制只有synchronized和volatile两种,java 5.0增加了一种新的机制:ReentrantLock;但是ReentrantLock并不是代替内置锁,而是作为一种可选择的高级功能;
1:Lock与ReentrantLock
Lock接口定义了一组抽象的加锁操作,与内置加锁机制不同,Lock提供了一种无条件的、可轮询的、定时的以及可中断的锁获取操作,所有加锁和解锁方法都是显示的。
Lock的实现中必须提供与内置加锁相同的内存可见性语义,但是在加锁语义、顺序保证以及性能特性方面有所不同;
Method Summary | |
---|---|
void | lock() Acquires the lock. |
void | lockInterruptibly() Acquires the lock unless the current thread is interrupted. |
Condition | newCondition() Returns a new Condition instance that is bound to this Lock instance. |
boolean | tryLock() Acquires the lock only if it is free at the time of invocation. |
boolean | tryLock(long time, TimeUnit unit) Acquires the lock if it is free within the given waiting time and the current thread has not been interrupted. |
void | unlock() Releases the lock. |
ReentrantLock实现了Lock接口,并且提供与synchronized相同的互斥性和内存可见性,与synchronized提供了可重入的加锁语义;
ReentrantLock还提供了Lock接口定义的获取锁的模式,与synchronized相比,为处理锁不可用性问题提供了更高的灵活性;
为什么要创建一种与内置锁如此相似的新的加锁机制?在大多数情况下,内置锁都能很好的工作,但是在功能上存在一些局限性,例如,无法中断一个正在等待获取锁的线程、或者无法在请求获取一个锁时无限的等待下去。内置锁必须在获取该锁的代码块中释放,这就简化了编码工作,并且与异常处理操作实现了很好的交互,但却无法实现非阻塞结构的加锁规则;
1.1 轮询锁与定时锁
1.2可中断的锁获取操作
2:性能因素考虑
3:公平性
4:在synchronized和ReentrantLock之间进行选择
5:读-写锁
public interface ReadWriteLock{
<span style="white-space:pre"> </span>Lock readLock();
<span style="white-space:pre"> </span>Lock writeLock();
}
public class ReadWriteMap<K,V>{
<span style="white-space:pre"> </span>private final Map<K,V> map;
<span style="white-space:pre"> </span>private finalReentrantReadWriteLock lock=new ReentrantReadWriteLock();
<span style="white-space:pre"> </span>private final Lock r=lock.readLock();
<span style="white-space:pre"> </span>private final Lock w=lock.writeLock();
<span style="white-space:pre"> </span>public V put(K key,V value){
<span style="white-space:pre"> </span>w.lock();
<span style="white-space:pre"> </span>try{
<span style="white-space:pre"> </span>return map.put(key,value);
<span style="white-space:pre"> </span>}finally{
<span style="white-space:pre"> </span>w.unlock();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public V get(K key){
<span style="white-space:pre"> </span>r.lock();
<span style="white-space:pre"> </span>try{
<span style="white-space:pre"> </span>return map.get(key);
<span style="white-space:pre"> </span>}finally{
<span style="white-space:pre"> </span>r.unlock();
<span style="white-space:pre"> </span>}<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>}
}