文章目录
前言
如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!
多线程开发B - ReadWriteLock 读写锁
ReadWriteLock将读锁和写锁相分离,在没有写的场景下,读读是不阻塞,无等待的,
最高级别的并发,注意的是在涉及写的时候,读和写都需要申请锁,因此写的过程中,可能会读到旧数据,导致数据不一致。
ReadWriteLock管理一组锁,一个是只读的锁,一个是写锁。
Java并发库中ReetrantReadWriteLock实现了ReadWriteLock接口并添加了可重入的特性。
代码示例:
/**
* 读锁
* @throws InterruptedException
* */
public static void read() throws InterruptedException {
try {
lock.readLock().lock();
long startTime = System.currentTimeMillis();
System.out.println("【read】 start !!!");
for (int i = 0; i < 4; i++) {
Thread.sleep(20);
System.out.printf("【%s】读取数据中...\n",Thread.currentThread().getName());
}
System.out.println("【read】 end 耗时"+((System.currentTimeMillis()-startTime))+"毫秒");
}finally {
System.out.println("--------读取结束---------");
lock.readLock().unlock();
}
}
/**
* 读锁 - 写锁
* @throws InterruptedException
* */
public static void readAndWrite() throws InterruptedException {
try {
lock.readLock().lock();
long startTime = System.currentTimeMillis();
System.out.println("【read】 start !!!");
for (int i = 0; i < 4; i++) {
Thread.sleep(20);
System.out.printf("【%s】读取数据中...\n",Thread.currentThread().getName());
}
write();
System.out.println("【read】 end 耗时"+((System.currentTimeMillis()-startTime))+"毫秒");
}finally {
System.out.println("--------读取结束---------");
lock.readLock().unlock();
}
}
/**
* 写锁
* @throws InterruptedException
* */
public static void write() throws InterruptedException {
try {
lock.writeLock().lock();
long startTime = System.currentTimeMillis();
System.out.println("【write】 start !!!");
for (int i = 0; i < 4; i++) {
Thread.sleep(20);
System.out.printf("【%s】写入数据中...\n",Thread.currentThread().getName());
}
System.out.println("【write】 end 耗时"+((System.currentTimeMillis()-startTime))+"毫秒");
}finally {
System.out.println("--------写入结束---------");
lock.writeLock().unlock();
}
}
/**
* 写锁 - 读锁
* @throws InterruptedException
* */
public static void writeAndRead() throws InterruptedException {
try {
lock.writeLock().lock();
long startTime = System.currentTimeMillis();
System.out.println("【write】 start !!!");
read();
for (int i = 0; i < 4; i++) {
Thread.sleep(20);
System.out.printf("【%s】写入数据中...\n",Thread.currentThread().getName());
}
System.out.println("【write】 end 耗时"+((System.currentTimeMillis()-startTime))+"毫秒");
}finally {
System.out.println("--------写入结束---------");
lock.writeLock().unlock();
}
}
1、读锁-读锁 效果:无阻塞 不获取锁
代码示例:
public static void main(String[] args) {
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(4);
//读锁
for (int i = 0; i < 4; i++) {
newFixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
read();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
newFixedThreadPool.shutdown();
}
效果:
说明:
读读是不阻塞,无等待的, 最高级别的并发,即读锁使用共享模式。
2、读锁-写锁 效果:阻塞 获取锁
代码示例:
public static void main(String[] args) {
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(4);
//读锁-写锁 效果:阻塞
for (int i = 0; i < 4; i++) {
newFixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
readAndWrite();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
newFixedThreadPool.shutdown();
}
效果:
说明:
锁升级,ReentrantReadWriteLock是不支持的,即读锁不能升级到写锁,也可以说一个获得了读锁的线程必须能看到前一个释放的写锁所更新的内容,读写锁之间为互斥。
3、写锁-读锁 效果:不阻塞 获取锁
代码示例:
public static void main(String[] args) {
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(4);
//读锁-写锁 效果:阻塞
for (int i = 0; i < 4; i++) {
newFixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
writeAndRead();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
newFixedThreadPool.shutdown();
}
效果:
说明:
ReentrantReadWriteLock支持锁降级,即写锁可以降级到读锁。
4、写锁 效果:不阻塞、获取锁
代码示例:
public static void main(String[] args) {
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(4);
//读锁-写锁 效果:阻塞
for (int i = 0; i < 4; i++) {
newFixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
write();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
newFixedThreadPool.shutdown();
}
效果:
说明:
写锁是互斥的,独立的,即写写之间是互斥模式。
总结:
- 读读是不阻塞,无等待的, 最高级别的并发,即读锁使用共享模式。
- 锁升级,ReentrantReadWriteLock是不支持的,即读锁不能升级到写锁,也可以说一个获得了读锁的线程必须能看到前一个释放的写锁所更新的内容,读写锁之间为互斥。
- ReentrantReadWriteLock支持锁降级,即写锁可以降级到读锁。
- 写锁是互斥的,独立的,即写写之间是互斥模式。