獨占鎖(寫鎖)/ 共享鎖(讀鎖)/ 互斥鎖
獨占鎖:指該鎖一次只能被一個線程所持有。
- ReentrantLock、Synchronized都是獨占鎖,并且是可重入鎖(遞歸鎖)
共享鎖:指該鎖可以被多個線程持有。 - ReentrantReadWriteLock的讀鎖是共享鎖,寫鎖是獨占鎖。
讀鎖的共享鎖可以保證并發(fā)讀的高效,讀寫,寫讀,寫寫的過程是互斥的。
寫操作:原子+ 獨占,整個過程是不可以被分割、被打斷的。
package com.company;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 手寫一個緩存
* 1.讀
* 2.寫
* 3.清空
*/
class MyCache{//資源類
//可見性,禁止指令重排
private volatile Map<String,Object> map = new HashMap<>();
//讀寫一體,讀的時候也是只有一個人可以讀,即排著隊讀
private ReadWriteLock rwlock = new ReentrantReadWriteLock();//可重入的讀寫鎖
public void put(String key,Object value){
rwlock.writeLock().lock();
try
{
System.out.println(Thread.currentThread().getName()+"正在寫入"+ key);
try {TimeUnit.MILLISECONDS.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}
map.put(key,value);
System.out.println(Thread.currentThread().getName()+"寫入完成");
}catch (Exception e){
e.printStackTrace();
}finally {
rwlock.writeLock().unlock();
}
}
public void get(String key) {
rwlock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "正在讀取");
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object result = map.get(key);
System.out.println(Thread.currentThread().getName() + "讀取完成" + result);
} catch (Exception e) {
e.printStackTrace();
} finally {
rwlock.readLock().unlock();
}
}
}
/**
* 讀、寫鎖
* 讀,大家可以一起讀
* 寫只允許一個人可以寫:原子、獨占
*
* 讀-讀可以共存
* 讀-寫、寫-寫u可以同時出現(xiàn)
*/
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCache myCache= new MyCache();
for (int i = 0; i < 3; i++) {
final int tempInt = i;
new Thread(()->{
myCache.put(tempInt+"",tempInt+"");
},"Thread_No"+i).start();
}
for (int i = 0; i < 3; i++) {
final int tempInt = i;
new Thread(()->{
myCache.get(tempInt+"");
},"Thread_No"+i).start();
}
}
}
Console:
- Thread_No0正在寫入0
- Thread_No0寫入完成
- Thread_No2正在寫入2
- Thread_No2寫入完成
- Thread_No1正在寫入1
- Thread_No1寫入完成
寫入與其他操作互斥。
Thread_No0正在讀取
Thread_No1正在讀取
Thread_No2正在讀取
Thread_No2讀取完成2
Thread_No0讀取完成0
Thread_No1讀取完成1
讀讀可以同時進(jìn)行。
讀寫分離,既保證了數(shù)據(jù)的一致性,比較于Synchronized這種重鎖,并發(fā)性得到了提升,因為可以同時讀了。