1:ReadWriteLock读写锁介绍
ReadWriteLock是JDK5中提供的读写分离锁。读写分离锁可以有效地帮助减少锁竞争,提升系统性能。用锁分离的机制来提升性能非常容易理解,比如线程A1、 A2. A3进行写操作,B1、B2、B3进行读操作,如果使用重入锁或者内部锁,从理论上说所有读之间、读与写之间、写和写之间都是串行操作。当B1进行读取时,B2、 B3 则需要等待锁。由于读操作并不对数据的完整性造成破坏,这种等待显然是不合理的。因此,读写锁就有了发挥功能的余地。
在这种情况下,读写锁允许多个线程同时读,使得B1、B2、B3之间真正并行。但是,考虑到数据完整性,写写操作和读写操作间依然是需要相互等待和持有锁的。总的来说,读写锁的访问约束情况如下
-
读-读不互斥: 读读之间不阻塞。
-
读-写互斥: 读阻塞写,写也会阻塞读。
-
写-写互斥:写写阻塞
果在系统中,读操作的次数远远大于写操作的次数,则读写锁就可以发挥最大的功效,提升系统的性能。
2:ReadWriteLock读写锁演示
我们来模拟在缓存(MyCache)中进行读,写分离操作演示
不使用ReadWriteLock的情况演示
class MyCache{
private volatile HashMap<String,String> hashMap= new HashMap();
public void put(String key,String value) throws InterruptedException {
System.out.println(Thread.currentThread().getName()+"----写入数据");
TimeUnit.MICROSECONDS.sleep(300);
hashMap.put(key,value);
System.out.println(Thread.currentThread().getName()+"----写入数据完成");
}
public void get(String key) throws InterruptedException {
System.out.println(Thread.currentThread().getName()+"读取数据");
TimeUnit.MICROSECONDS.sleep(300);
hashMap.get(key);
System.out.println(Thread.currentThread().getName()+"读取数据完成");
}
}
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCache myCache = new MyCache();
for (int i=0;i<5;i++){
final int inttempt=1;
new Thread(()->{
try {
myCache.put(inttempt+" ",inttempt+"");
} catch (InterruptedException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
for (int i=0;i<5;i++){
final int inttempt=1;
new Thread(()->{
try {
myCache.get(inttempt+" ");
} catch (InterruptedException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
使用ReadWriteLock的情况演示
class MyCache{
private volatile HashMap<String,String> hashMap= new HashMap();
3 private ReadWriteLock readWriteLock= new ReentrantReadWriteLock();
public void put(String key,String value) throws InterruptedException {
5 readWriteLock.writeLock().lock();
try{
System.out.println(Thread.currentThread().getName()+"----写入数据");
TimeUnit.MICROSECONDS.sleep(300);
hashMap.put(key,value);
System.out.println(Thread.currentThread().getName()+"----写入数据完成");
}catch(Exception e){
e.printStackTrace();
}finally{
readWriteLock.writeLock().unlock();
}
}
public void get(String key) throws InterruptedException {
16 readWriteLock.readLock().lock();
try{
System.out.println(Thread.currentThread().getName()+"读取数据");
TimeUnit.MICROSECONDS.sleep(300);
hashMap.get(key);
System.out.println(Thread.currentThread().getName()+"读取数据完成");
}catch(Exception e){
e.printStackTrace();
}finally{
readWriteLock.readLock().unlock();
}
}
}
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCache myCache = new MyCache();
for (int i=0;i<5;i++){
final int inttempt=1;
new Thread(()->{
try {
myCache.put(inttempt+" ",inttempt+"");
} catch (InterruptedException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
for (int i=0;i<5;i++){
final int inttempt=1;
new Thread(()->{
try {
myCache.get(inttempt+" ");
} catch (InterruptedException e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}
读线程完全并行,而写会阻塞读。如果使用读写锁这段程序2秒就可以结束,如果使用可重入锁和内部锁,整个程序执行时间将要到5秒左右