读写锁
读写锁:ReentrantReadWriteLock
读操作共享资源,写操作独占资源
防止在写操作的过程中被其他线程读取(读取不完整)
缺点:可能造成读的饥饿问题,一直读,没有写
//资源类
class MyCache{
//创建资源集合
private volatile Map<String, Object> map = new HashMap<>();
private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
//写数据
public void put(String key,Object value){
//添加写锁
readWriteLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName()+":正在做写操作"+key);
TimeUnit.MICROSECONDS.sleep(300); //等待300毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//解锁
readWriteLock.writeLock().unlock();
}
//放数据
map.put(key, value);
System.out.println(Thread.currentThread().getName()+"写完了"+key);
}
//取数据
public Object get(Object key){
//添加读锁
readWriteLock.readLock().lock();
Object result = null;
try {
System.out.println(Thread.currentThread().getName()+":正在做读操作"+key);
TimeUnit.MICROSECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//解锁
readWriteLock.readLock().unlock();
}
//取数据
result = map.get(key);
System.out.println(Thread.currentThread().getName()+"取完了"+key);
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(num+"", num+"");
},String.valueOf(i)).start();
}
//创建多个线程取数据
for (int i = 1; i <=5; i++) {
final int num = i;
new Thread(()->{
myCache.get(num+"");
},String.valueOf(i)).start();
}
}
}
锁降级
降写锁降级为读锁
写锁是可以降级为读锁的;写锁只有一个,当写锁降级为读锁时,所有的都是读。
//写锁降级为读锁
public class Demo1 {
public void downgrade(){
//可重入读写锁对象
ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();//读锁
ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();//写锁
System.out.println(Thread.currentThread().getName()+"尝试获取写锁");
writeLock.lock();
try{
System.out.println(Thread.currentThread().getName()+"获取到了写锁");
System.out.println(Thread.currentThread().getName()+"降级获取读锁");
readLock.lock(); //降级为读锁
try{
}finally {
readLock.unlock();
}
}finally {
writeLock.unlock();
}
}
public static void main(String[] args) {
Demo1 demo1 = new Demo1();
new Thread(()->demo1.downgrade(),"线程1").start();
new Thread(()->demo1.downgrade(),"线程2").start();
}
}