java鎖:第四章:讀寫鎖
理論:
未使用讀寫鎖的代碼:
package com.javaliao.backstage;
import java.util.HashMap;
import java.util.Map;
class Data{
private volatile Map map = new HashMap<String,Object>();
//寫
public void put(String key,Object value){
System.out.println(Thread.currentThread().getName()+"\t 正在寫入:"+key);
try {
Thread.sleep(300);
map.put(key,value);
System.out.println(Thread.currentThread().getName()+"\t 寫入完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//讀
public void get(String key){
System.out.println(Thread.currentThread().getName()+"\t 正在讀取");
try {
Thread.sleep(300);
Object value = map.get(key);
System.out.println(Thread.currentThread().getName()+"\t 讀取完成:"+value);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Demo {
public static void main(String[] args) {
Data data = new Data();
//五個(gè)寫的線程
for (int i = 0; i < 5; i++) {
final int tempInt = i;
new Thread(()->{
data.put(tempInt+"",tempInt+"");
},String.valueOf(i)).start();
}
//五個(gè)讀的線程
for (int i = 0; i < 5; i++) {
final int tempInt = i;
new Thread(()->{
data.get(tempInt+"");
},String.valueOf(i)).start();
}
}
}
控制臺:
可以看到寫的操作原子性和獨(dú)占性沒有得到保證,0線程正在寫入共享資源的時(shí)候,其他線程有寫入和讀取的共享資源操作,導(dǎo)致數(shù)據(jù)不一致。
是否可以添加Lock鎖解決原子性和獨(dú)占性的問題?
不可以,因?yàn)樘砑?/p>
private Lock lock = new ReentrantLock();
只能保證一個(gè)線程讀,不能讓多個(gè)線程同時(shí)讀取,不符合實(shí)際需求。
使用ReentrantReadWriteLock解決原子性和獨(dú)占性,可以很好的解決并發(fā)性和數(shù)據(jù)的一致性
讀寫鎖的代碼:
package com.javaliao.backstage;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
class Data{
private volatile Map map = new HashMap<String,Object>();
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void put(String key,Object value){
//寫鎖
lock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName()+"\t 正在寫入:"+key);
Thread.sleep(300);
map.put(key,value);
System.out.println(Thread.currentThread().getName()+"\t 寫入完成");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.writeLock().unlock();
}
}
public void get(String key){
//讀鎖
lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName()+"\t 正在讀取");
Thread.sleep(300);
Object value = map.get(key);
System.out.println(Thread.currentThread().getName()+"\t 讀取完成:"+value);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.readLock().unlock();
}
}
}
public class Demo {
public static void main(String[] args) {
Data data = new Data();
//五個(gè)寫的線程
for (int i = 0; i < 5; i++) {
final int tempInt = i;
new Thread(()->{
data.put(tempInt+"",tempInt+"");
},String.valueOf(i)).start();
}
for (int i = 0; i < 5; i++) {
final int tempInt = i;
new Thread(()->{
data.get(tempInt+"");
},String.valueOf(i)).start();
}
}
}
控制臺:
比較: