目录
1、读写锁的使用
package com.example.read_write_lock;
import java.sql.Time;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 读写锁时间实践
* eg:多线程往map集合里面写数据,多线程读取map集合里面的数据
* 如果不加读写锁会出现什么问题?
* 就会出现写线程还没有把数据写到map集合里面,读线程就已经开始读操作了,此时肯定是读取不到数据的
*/
//资源类
class MyCache{
//创建map集合
private volatile Map<String,Object> map = new HashMap<>();
//创建读写锁
private ReadWriteLock rdLock = new ReentrantReadWriteLock();
//创建写方法
public void put(String key,String value) {
//加写锁
rdLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName()+"正在写操作"+key);
//等待一段时间
TimeUnit.MICROSECONDS.sleep(300);
//放数据
map.put(key,value);
System.out.println(Thread.currentThread().getName()+"写完了"+key);
} catch (Exception e) {
e.printStackTrace();
}finally {
//释放锁
rdLock.writeLock().unlock();
}
}
//创建读方法
public Object get(String key) {
//加读锁
rdLock.readLock().lock();
Object result=null;
try {
System.out.println(Thread.currentThread().getName()+"正在读操作"+key);
//等待一段时间
TimeUnit.MICROSECONDS.sleep(300);
//读数据
result=map.get(key);
System.out.println(Thread.currentThread().getName()+"读完了"+key);
} catch (Exception e) {
e.printStackTrace();
}finally {
//释放读锁
rdLock.readLock().unlock();
}
return result;
}
}
public class ReadWriteLockDemo {
public static void main(String[] args) throws Exception {
//创建资源类对象
MyCache myCache = new MyCache();
//5个线程负责写
for (int i = 1; i <= 5; i++) {
final int num = i;
new Thread(()->{
myCache.put(num+"",num+"");
},String.valueOf(i)).start();
}
TimeUnit.SECONDS.sleep(3);
//5个线程负责读
for (int i = 1; i <= 5; i++) {
final int num=i;
new Thread(()->{
myCache.get(num+"");
},String.valueOf(i)).start();
}
}
}
2、 锁降级
package com.example.read_write_lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 锁降级
* 写锁可以降级为读锁,反之不行
*/
public class LockDegradation {
public static void main(String[] args) {
//可重入读写锁对象
ReadWriteLock rwlock=new ReentrantReadWriteLock();
Lock readLock = rwlock.readLock();
Lock writeLock = rwlock.writeLock();
//写锁
writeLock.lock();
System.out.println("writeLock");
//读锁
readLock.lock();
System.out.println("readLock");
writeLock.unlock();
readLock.unlock();
}
}
注:在未释放写锁之前的读锁代码照旧会打印,是因为写锁可以降级为读锁,反之不行,如果此时将①和②位置调换后运行,只会打印②,而①会等待;因为②没有释放锁,此时不能降级;