-
ReentrantLock比synchronized更具有伸缩性,当有多个线程竞争锁的时候,reentrantLock比synchronized的吞吐量好
简而言之,就是在访问被reentranLock加锁的共享资源时,jvm将花费更少的时间来调度线程,更多的时间去执行线程。 -
ReadWriteLock接口有两个方法:
Lock readLock();
Lock writeLock();
这两个方法,一个用来获取读锁,一个用来获取写锁。
也就是说一个资源可以被多个读线程访问,或者被一个写线程访问。
但是是不能同时存在读和写的线程。
**适用的场景是某个共享资源存在多个读操作,而存在少量的写操作。 -
从源码中可以看出,ReadWriteLock和Lock之间不存在继承关系。
只不过在ReadWriteLock的内部声明了两个返回值是Lock类型的方法。
来实现锁之间的并存以及互斥操作。 -
ReentrantReadWriteLock是唯一的实现类,在有多个线程进行读取的时候,是可以允许读线程进行共享访问的,写如线程依然必须是互斥的。
-
reentrantReadWriteLock的特点:
5.1 公平性:由于读线程之间没有竞争,所以读线程之间没有什么公平性和非公平性,但是在写操作的时候,写操作获得锁之后,其它的写操作或者读操作之间是会被推迟的。所以非公平醒锁的吞吐量是高于公平锁的。
5.2 重入性:允许读线程和写线程按照顺序去获取锁,当然,只有写锁释放之后,读线程才能获取重入锁,写线程获取写入锁之后可以再次获取读取锁,但是读线程获取读取锁之后,是不可以获取写入锁的,另外读写锁最多支持65535个递归写入锁和65535个递归读取锁。
5.3锁降级:写线程获取写入锁之后,还可以获取读取锁,然后释放写入锁,这样就从写入锁变成了读取锁,从而实现了锁降级。
5.4锁升级:读取锁是不能直接升级为写锁的,因为获取一个写锁需要释放所有的读取锁。
所以有两个读取锁都试图获取写锁的时候,都不释放锁的情况下,就会发生死锁。
5.5锁中断:读锁和写锁都直接获取锁中途被中断。
5.6总结一下:
读-读不互斥
读-写互斥
写-写互斥 -
实例:
public class test{private ReentranReadWriteLock lock = new Reent…;
public static void main(String[] args){
final Test tes = new Test();
new Thread(){
public void run(){
test.get(Thread.getCurrentThread());
}
}.start();new Thread(){ public void run(){ test.get(Thread.getCurrentThread()); } }.start();
}
public synchronized void get(Thread thread){
long start = System.currentTimeMillis();
while(System.currentTimeMillis()-start <= 1){
System.out.println(thread.getName()+“正在进行读操作”);
}
System.out.println(thread.getName()+“读操作完毕”);
}
}
注意:这段代码的输出顺序为:
直到Thread1读操作结束之后,释放了锁资源后,thread2才能获得锁,执行读操作。显然这样的效率是不高的,应该适用reentrantreadwritelock锁
改造get()如下:
public void get(Thread thread){
reentrantReadWriteLock.readLock().lock();//获取读锁
try{
//业务操作
}finally{
//释放锁
reentrantReadWrite.readLock().unLock();
}
}
输出结果可以看出,两个线程可以同时读取。