文章目錄
- 1:ReadWriteLock讀寫鎖介紹
- 2:ReadWriteLock讀寫鎖示範
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秒左右