Lock与ReentrantLock
-
Lock提供了一种无条件的、可轮询的、定时的以及可中断的锁获取操作
-
ReentrantLock实现了Lock接口,并提供了与synchronized相同的互斥性和内存可见性,还提供了可重入的加锁语义
-
可中断的锁获取操作:
public boolean sendOnSharedLine(String message) throws InterrputedException{
lock.lockInterruptibly();
try{
return cancellableSendOnSharedLine(message);
} finally{
lock.unlock();
}
}
公平性:
-
ReentrantLock的构造函数中提供了两种公平性选择:创造一个非公平的锁(默认)或一个公平的锁
-
在公平的锁上,线程将按照他们发出请求的顺序来获得锁,但在非公平的锁上,允许“插队”;当一个线程请求非公平的锁时,如果在发出请求的同时该锁的状态变为可用,那么这个线程将跳过队列中所有的等待线程并获得这个锁
-
在公平的锁中,如果有另一个线程有这个锁或者有其他线程在队列中等待这个锁,那么新发出请求的线程将被放入队列中。在非公平的锁中,只有当锁被某个线程持有时,新发出请求的线程才会被放入队列
-
即使对于公平锁而言,可轮询的tryLock依然会插队
synchronized VS ReentrantLock
-
ReentrantLock的危险性比同步机制高,可能会忘记在finally中调用unlock
-
内置锁在线程转储中能给出在哪些调用帧中获得了哪些锁,并能检测和识别发生死锁的线程
读-写锁
- ReentrantReadWriteLock实现了ReadWriteLock接口,为两种锁都提供了可重入的加锁语义
private ReadWriteLock rwl = new ReentrantReadWriteLock();//定义读写锁
public Object getData(String key){
//使用读写锁的基本结构
rwl.readLock().lock();
Object value = null;
try{
value = cache.get(key);
if(value == null){
rwl.readLock().unlock();
rwl.writeLock().lock();
try{
// Recheck state because another thread might have
// acquired write lock and changed state before we did.
if(value == null){
value = "aaaa";//写入数据
}
}finally{
rwl.writeLock().unlock();
}
rwl.readLock().lock();
}
}finally{
rwl.readLock().unlock();
}
return value;
}
- 读-写锁允许多个读线程并发地访问被保护的对象,当访问以读操作为主的数据结构时,它能提高程序的可伸缩性;其他情况下,性能比独占锁差一点,因为复杂性更高