首页 > 技术文章 > ReadWriteLock

jzspace 2020-05-24 16:45 原文

ReadWriteLock:读写锁

已知实现类,ReentrantReadWriteLock -->可重入读写锁

ReadWriteLock维护一对关联的locks,一个用于只读操作,一个用于写入操作。

read lock可以有多线程同时读取,write lock只能有一个线程去写。

/*
希望写入的时候,只有一个线程操作写入。因为写入肯定要保证原子性。
读取的时候,是所有线程同时读取。那么就使用读写锁。
读写锁 ReadWriteLock
别名:
独占锁(写锁):一次只能被一个线程占有。
共享锁(读锁):多个线程可以同时占有。
读锁 选择读锁 ReadWriteLock.ReadLock().lock();
写锁 选择写锁 ReadWriteLock.WriteLock().lock();
其实具体操作和lock基本无区别
但是ReadWriteLock是更细粒度的控制的锁
*/
public class CallAble {
public static void main(String[] args) {
MycacheLock mycache = new MycacheLock();
for (int i = 1; i <= 5; i++) {
final int temp = i;
new Thread(()->{
mycache.set(temp,"--"+temp);
},String.valueOf(i)).start();
}
for (int i = 1; i <= 5; i++) {
final int temp = i;
new Thread(()->{
mycache.get(temp);
},String.valueOf(i)).start();
}

}
}

//加锁的自定义缓冲区
class MycacheLock{

private volatile Map<Integer,String> map = new HashMap<>();
//private Lock lock = new ReentrantLock();
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
//写入
public void set(Integer key,String value){
//lock.lock();
readWriteLock.writeLock().lock();//加入写锁
try {
System.out.println(Thread.currentThread().getName()+ "写入");
map.put(key,value);
System.out.println(Thread.currentThread().getName()+ "写完----->");
} catch (Exception e) {
e.printStackTrace();
} finally {
//lock.unlock();
readWriteLock.writeLock().unlock();//写锁解锁
}
}
//读取
public void get(Integer key){
readWriteLock.readLock().lock();//加入读锁
try {
System.out.println(Thread.currentThread().getName()+ "读取");
String s = map.get(key);
System.out.println(Thread.currentThread().getName()+ "读完----->");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.readLock().unlock();
}
}
}
//未加锁的自定义缓冲区
//未加锁时写入还没写完的时候被其他线程插入了,所以在上面加入了读写锁
class Mycache{

private volatile Map<Integer,String> map = new HashMap<>();

public void set(Integer key,String value){
System.out.println(Thread.currentThread().getName()+ "写入");
map.put(key,value);
System.out.println(Thread.currentThread().getName()+ "写完----->");
}

public void get(Integer key){
System.out.println(Thread.currentThread().getName()+ "读取");
String s = map.get(key);
System.out.println(Thread.currentThread().getName()+ "读完----->");
}
}

推荐阅读