readLock()和writeLock()都是ReadWriteLock接口中定义的方法,用于获取读锁和写锁。
readLock()
方法返回一个读锁,允许同时获取该锁,以进行并发读取操作。如果当前已有一个写锁或其他线程正在请求写锁,则读锁会被阻塞,直到所有写锁请求完成并释放锁为止。读锁和写锁之间是互斥的。
writeLock()
方法返回一个写锁,只允许获取该锁,以进行写入操作。如果当前已有一个读锁或其他线程正在请求读锁,则写锁会被阻塞,直到所有读锁请求完成并释放锁为止。写锁是独占的,同一时间只能有一个线程持有写锁。
在使用读写锁时,应该根据具体的业务场景和需求选择适当的锁类型。如果共享资源的读取操作远远超过写入操作,那么使用读写锁可以提高系统的并发性能。如果写入操作非常频繁,那么使用读写锁可能会导致读取操作的性能下降,因为读取线程需要等待写入线程释放写锁。此外,读写锁也需要消耗额外的系统资源,因此应该避免不必要的锁竞争。
🛸情景引入
我们先看下面这段代码
本来应该是1写入,然后1写入完全
但是现在1写入后,紧跟着的是3写入
这明显是错误的
⭐解决问题
下面我们来加上锁,解决问题
package org.Test6;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCacheLock myCache = new MyCacheLock();
//写入
for(int i=1;i<=5;i++){
final int temp=i;
new Thread(()->{
myCache.put(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<String,Object> map = new HashMap<>();
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
//存 写 写入的时候
// 只希望只有一个线程去写
public void put(String key,Object value){
readWriteLock.writeLock().lock(); //加锁
try {
System.out.println(Thread.currentThread().getName()+"写入"+key);
map.put("key","value");
System.out.println(Thread.currentThread().getName()+"写入结束");
} catch (Exception e) {
e.printStackTrace();
}finally {
readWriteLock.writeLock().unlock(); //解锁
}
}
//取 读
//读的时候,所有人都可以读
public void get(String key){
readWriteLock.readLock().lock(); //加锁
try {
System.out.println(Thread.currentThread().getName()+"读取"+key);
Object o=map.get("key");
System.out.println(Thread.currentThread().getName()+"读取结束");
} catch (Exception e) {
e.printStackTrace();
}finally {
readWriteLock.readLock().unlock(); //解锁
}
}
}
独占锁(写锁):一次只能被一个线程占有
共享锁(读锁):多个线程可以同时占有