当前位置:   article > 正文

关于读写锁-ReentrantReadWriteLock

关于读写锁-ReentrantReadWriteLock
读写锁 ReentrantReadWriteLock,其核心就是实现 读写分离,多哦,突然记得之前学的COW容器也是读写分离的。好了,读写分离有什么好处了,就是在高并发访问下,尤其是读多写少的情况下,性能要远高于重入锁。
之前学synchronized、ReentrantLock的时候,我们都知道,同一时间内,只能有一个线程进行访问被锁定的代码,那么读写锁则不同,其本质是分成两个锁,就是读锁和写锁。在读锁下,多个线程可以并发的进行访问,但是在写锁的时候,只能一个一个的访问。只有是读的情况下是可以并发访问的,而多个线程访问写或者多个线程分别访问读和写,都是一个一个地访问的。
有这么一个口诀:读读共享,写写互斥,读写互斥。

1、下面的例子是看如何使用,而且测一下是不是读读共享。
  1. public class UseReentrantReadWriteLock {
  2. private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
  3. //原来读锁和写锁都是用ReentrantReadWriteLock创建出来的,哪个方法需要什么锁,就调用什么锁的lock()方法,不过最后记得要释放锁。
  4. private ReadLock rLock = rwLock.readLock();
  5. private WriteLock wLock = rwLock.writeLock();
  6. public void read(){ //读操作
  7. try{
  8. //因为这里模拟的是读操作,所以调用的是读锁的lock方法
  9. rLock.lock();
  10. System.out.println("线程:"+Thread.currentThread().getName()+"进入读操作");
  11. Thread.sleep(2000);
  12. }catch(Exception e){
  13. e.printStackTrace();
  14. }finally{
  15. System.out.println("线程:"+Thread.currentThread().getName()+"执行完读操作");
  16. rLock.unlock();
  17. }
  18. }
  19. public void write(){ //写操作
  20. try{
  21. //因为这里模拟的是写操作,所以调用的是写锁的lock方法。
  22. wLock.lock();
  23. System.out.println("线程:"+Thread.currentThread().getName()+"进入写操作");
  24. Thread.sleep(2000);
  25. }catch(Exception e){
  26. e.printStackTrace();
  27. }finally{
  28. System.out.println("线程:"+Thread.currentThread().getName()+"执行完写操作");
  29. wLock.unlock();
  30. }
  31. }
  32. public static void main(String[] args) {
  33. UseReentrantReadWriteLock urLock = new UseReentrantReadWriteLock();
  34. Thread t1 = new Thread(new Runnable(){
  35. @Override
  36. public void run() {
  37. urLock.read();
  38. }
  39. },"t1");
  40. Thread t2 = new Thread(new Runnable(){
  41. @Override
  42. public void run() {
  43. urLock.read();
  44. }
  45. },"t2");
  46. t1.start();
  47. t2.start();
  48. }
  49. }
执行结果:可以发现,线程1和线程2是同时获得读锁然后进入读方法的,也是同时的完成。所以说读读是共享的,不存在单个线程获得锁执行方法的说法。
  1. 线程:t2进入读操作
  2. 线程:t1进入读操作
  3. 线程:t2执行完读操作
  4. 线程:t1执行完读操作

2、那么下面是测试写写是否是互斥的。
我们将上面的线程1和线程2都换成调用写操作就可以测试了。
  1. UseReentrantReadWriteLock urLock = new UseReentrantReadWriteLock();
  2. Thread t1 = new Thread(new Runnable(){
  3. @Override
  4. public void run() {
  5. urLock.write();
  6. }
  7. },"t1");
  8. Thread t2 = new Thread(new Runnable(){
  9. @Override
  10. public void run() {
  11. urLock.write();
  12. }
  13. },"t2");
  14. t1.start();
  15. t2.start();
执行结果:可以看到,线程2先获取了写锁然后执行写方法,当线程2执行完释放锁后,线程1才获得写锁然后执行写操作。所以说写写是互斥的。
  1. 线程:t2进入写操作
  2. 线程:t2执行完写操作
  3. 线程:t1进入写操作
  4. 线程:t1执行完写操作

3、最后看一下读写互斥,我们将线程1改为读操作,线程2是写操作。
  1. UseReentrantReadWriteLock urLock = new UseReentrantReadWriteLock();
  2. Thread t1 = new Thread(new Runnable(){
  3. @Override
  4. public void run() {
  5. urLock.read();
  6. }
  7. },"t1");
  8. Thread t2 = new Thread(new Runnable(){
  9. @Override
  10. public void run() {
  11. urLock.write();
  12. }
  13. },"t2");
  14. t1.start();
  15. t2.start();
执行结果:我们可以看到,写操作和读操作确实是互斥的,只有其中一个操作做完,另一个操作才能进行。
  1. 线程:t2进入写操作
  2. 线程:t2执行完写操作
  3. 线程:t1进入读操作
  4. 线程:t1执行完读操作
读写锁还挺有意思的。。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/336587
推荐阅读
相关标签
  

闽ICP备14008679号