读写锁是两把锁,声明的话是一个对象,锁也是锁一个方法。但是分读锁,和写锁。
写锁与写锁之间是不互斥的,可以有多个线程同时读;
但是写锁是互斥的,同一时间只能有一个线程写;
有一个特点:
当有线程在写是,是不可以读的、要等写锁被释放后,才可以读。
public class TestReentrantReadWriteLock {
private static final ReadWriteLock lock = new ReentrantReadWriteLock();
static ExecutorService es = Executors.newFixedThreadPool(5);
public static void main(String[] args) {
String name1 = "小明";
String name2 = "小红";
es.submit(new Runnable() {
@Override
public void run() {
writeOnlyOne(name1);
}
});
es.submit(new Runnable() {
@Override
public void run() {
readOnlyOne(name1);
}
});
es.submit(new Runnable() {
@Override
public void run() {
readOnlyOne(name2);
}
});
es.submit(new Runnable() {
@Override
public void run() {
writeOnlyOne(name1);
}
});
es.submit(new Runnable() {
@Override
public void run() {
writeOnlyOne(name2);
}
});
es.shutdown();
es.shutdown();
// 结果:
// 小明开始写2022-01-27 04:22:25
//小明写完了2022-01-27 04:22:30
//小明开始读2022-01-27 04:22:30
//小红开始读2022-01-27 04:22:30
//小明读完了2022-01-27 04:22:32
//小红读完了2022-01-27 04:22:32
//小明开始写2022-01-27 04:22:32
//小明写完了2022-01-27 04:22:37
//小红开始写2022-01-27 04:22:37
//小红写完了2022-01-27 04:22:42
}
public static void readOnlyOne(String name) {
try {
lock.readLock().lockInterruptibly();
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println(String.format("%s开始读", name) + getNow());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(String.format("%s读完了", name) + getNow());
lock.readLock().unlock();
}
public static void writeOnlyOne(String name) {
try {
lock.writeLock().lockInterruptibly();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
System.out.println(String.format("%s开始写", name) + getNow());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(String.format("%s写完了", name) + getNow());
lock.writeLock().unlock();
}
public static String getNow() {
Date date = new Date(System.currentTimeMillis());
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
return dateFormat.format(date);
}
}
看下结果:
// 结果:
// 小明开始写2022-01-27 04:22:25
//小明写完了2022-01-27 04:22:30
//小明开始读2022-01-27 04:22:30
//小红开始读2022-01-27 04:22:30
//小明读完了2022-01-27 04:22:32
//小红读完了2022-01-27 04:22:32
//小明开始写2022-01-27 04:22:32
//小明写完了2022-01-27 04:22:37
//小红开始写2022-01-27 04:22:37
//小红写完了2022-01-27 04:22:42
小明开始写的时候
小明和小红都不能读
5秒后小明写完了
小明和小红都可以读,而且是同时读
此时注意
小明和小红在读期间
小明是不能写的
2秒后
小明小红读完了
小明可以写了
小明开始写
5秒后
小红才能开始写
5秒后
小红写完了
总结一下上面漏的一点:
就是读锁被抢后,写锁是不能获取的
在读期间,不能写
在写期间,不能读
读锁不互斥
写锁互斥