ReadWriteLock
public interface ReadWriteLock {
Lock readLock();
Lock writeLock();
}
A ReadWriteLock维护一对关联的locks ,一个用于只读操作,一个用于写入。
- read lock可以由多个阅读器线程同时进行,只要没有writer。
- write lock是独家的。
读锁是共享锁,写锁是排他锁。 读读可以共存。读写,写写不能共存。
ReadWrite的实现类是ReentrantReadWriteLock
ReentrantReadWriteLock
public class ReentrantReadWriteLock
implements ReadWriteLock, java.io.Serializable{
}
具有以下属性:
可选的策略:
此类不会强加读卡器或写入器优先顺序锁定访问。 但是,它确实支持可选的公平政策。
public ReentrantReadWriteLock() {
this(false);//默认不公平锁
}
public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();//根据fair选择
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
非公平模式(默认)
线程对锁进行争抢,吞吐量大
公平模式
类似于排队,分配给等待最久的线程(写优先)
如果写锁定或有等待的写入程序线程,尝试获取公平读锁(不可重入)的线程将阻塞,直到最旧的当前正在等待的写入程序线程获取并释放写入锁之后,该线程才会获取读锁定。(没有其他线程的写锁或写请求) 当然,如果一个等待的作家放弃了等待,留下一个或多个阅读器线程作为队列中最长的服务器,其中写锁定空闲,那么这些读取器将被分配读取锁定。
尝试获取公平写入锁(非重入)的线程将阻止,除非读锁定和写锁定都是空闲的(这意味着没有等待线程)。 (请注意,无阻塞ReentrantReadWriteLock.ReadLock.tryLock()和ReentrantReadWriteLock.WriteLock.tryLock()方法不符合此公平的设置,如果可能,将立即获取锁定,而不管等待线程。)
可重入
可重入: 拥有锁的线程再次重复申请同一个锁,
此锁允许reader和writer按照 ReentrantLock 的样式重新获取读/写锁。在写线程保持的所有写锁都已释放后,才允许重入reader使用读锁 writer可以获取读取锁,但reader不能获取写入锁。
public class RWTest {
private static ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
public static void main(String[] args) {
RWTest rwTest = new RWTest();
new Thread(()->{rwTest.write();}).start();
}
public synchronized void read(){
lock.readLock().lock();
System.out.println("read come in");
lock.readLock().unlock();
System.out.println("read go out");
}
public synchronized void write(){
// 在写时调用读
lock.writeLock().lock();
System.out.println("w come in");
read();
lock.writeLock().unlock();
System.out.println("w go out");
}
}
w come in
read come in
read go out
w go out
public class RWTest {
private static ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
public static void main(String[] args) {
RWTest rwTest = new RWTest();
new Thread(()->{rwTest.read();}).start();
}
public synchronized void read(){
lock.readLock().lock();
System.out.println("read come in");
//读时写-> 死锁
write();
lock.readLock().unlock();
System.out.println("read go out");
}
锁降级
重入还允许从写入锁降级为读取锁,实现方式是:先获取写入锁,然后获取读取锁,最后释放写入锁。
允许写锁降级为读锁,但是从读锁定升级到写锁是不可能的。
public class RWTest {
private static ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
public static void main(String[] args) {
RWTest rwTest = new RWTest();
new Thread(()->{rwTest.write();}).start();
}
public synchronized void read(){
lock.readLock().lock();
System.out.println("read come in");
lock.readLock().unlock();
System.out.println("read go out");
}
public synchronized void write(){
lock.writeLock().lock();
System.out.println("w come in");
lock.readLock().lock();
System.out.println("read was lock");
lock.writeLock().unlock();
System.out.println("w go out");
lock.readLock().unlock();
System.out.println("read unlock");
}
w come in
read was lock
w go out
read unlock
可中断
中断: 在等待锁的时候可以放弃等待 读锁和写锁都支持中断
Condition支持
写入锁提供了一个Condition实现,这个Condition当然只能用于写锁。
public Condition newCondition() {
return sync.newCondition();
}
读锁不支持Condition和readLock().newCondition()抛出UnsupportedOperationException异常 。
监控
提供确定锁是否被持有等辅助方法