读写锁
并发读, 独占写, 读锁和写锁都可能发生死锁
一个资源可以被多个读线程访问,或者可以被一个写线程访问, 但是不能同时存在读写线程, 读写互斥、写写互斥、读读共享。
缺点:
- 造成锁饥饿,一直读,没法写操作, 比如坐地铁,100个人上车1个人下车,一直堵着下不了
- 读的时候,哪个线程都不可以写, 写的时候,自己线程可以读,其他线程不能读
ps:读写锁本质上是一种自旋锁
代码例子:缓存读写
//资源类
class MyCache{
private volatile Map<String, Object> map = new HashMap<>();
private ReadWriteLock rwLock = new ReentrantReadWriteLock();
//放数据
public void put(String key, Object value) {
//添加写锁
try {
rwLock.writeLock().lock();
System.out.println(Thread.currentThread().getName() + "+++正在写操作");
//模拟写的很慢
TimeUnit.MICROSECONDS.sleep(300);
//放数据
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "+++写操作完成√√√√");
}catch (InterruptedException e) {
e.printStackTrace();
}finally {
//释放写锁
rwLock.writeLock().unlock();
}
}
//取数据
public Object get(String key) {
Object result = null;
//模拟取的很慢
try {
rwLock.readLock().lock();
System.out.println(Thread.currentThread().getName() + "---读取操作");
TimeUnit.MICROSECONDS.sleep(300);
result = map.get(key);
System.out.println(Thread.currentThread().getName() + "---取完了" + key + "::" + result);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
rwLock.readLock().unlock();
}
return result;
}
}
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCache myCache = new MyCache();
//放数据线程
for (int i = 1; i <= 5; i++) {
final int num = i;
new Thread(()->{
myCache.put(String.valueOf(num), String.valueOf(num));
},String.valueOf(i)).start();
}
//取数据线程
for (int i = 1; i <= 5; i++) {
final int num = i;
new Thread(()->{
myCache.get(String.valueOf(num));
},String.valueOf(i)).start();
}
}
}
锁降级: 将写锁可降级为读锁
代码例子 锁降级
写锁降级为读锁
public class 锁降级Demo {
public static void main(String[] args) {
//可重入读写锁对象
ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();
//锁降级 , 写的时候在此线程还能获取到读锁,而读的时候不能获取到写锁
//1.获取写锁
writeLock.lock();
System.out.println("哈哈哈");
//2.获取写锁
readLock.lock();
System.out.println("read");
//3.释放写锁
writeLock.unlock();
//4.释放读锁
readLock.unlock();
}
}