当前位置:   article > 正文

java新特性——读写锁ReadWriteLock_2,jdk5以后提供的读写锁体现一种什么思想?目的是什么?

2,jdk5以后提供的读写锁体现一种什么思想?目的是什么?
from URL : http://hi.baidu.com/zhizhesky/blog/item/cabcbb515b9b6808377abe5f.html

在上文中提到了Lock接口以及对象,使用它,很优雅的控制了竞争资源的安全访问,但是这种锁不区分读写,称这种锁为普通锁。为了提高性能,Java提供了读写锁,在读的地方使用读锁,在写的地方使用写锁,灵活控制, 如果没有写锁的情况下,读是无阻塞的,在一定程度上提高了程序的执行效率。
Java中读写锁有个接口java.util.concurrent.locks.ReadWriteLock,也有具体的实现ReentrantReadWriteLock,详细的API可以查看JavaAPI文档。

ReentrantReadWriteLock 和 ReentrantLock 不是继承关系,但都是基于 AbstractQueuedSynchronizer 来实现。

lock方法 是基于CAS 来实现的

注意: 在同一线程中,持有读锁后,不能直接调用写锁的lock方法 ,否则会造成死锁。

下面这个例子是在文例子的基础上,将普通锁改为读写锁,并添加账户余额查询的功能,代码如下:
  1. import java.util.concurrent.ExecutorService;
  2. import java.util.concurrent.Executors;
  3. import java.util.concurrent.locks.ReadWriteLock;
  4. import java.util.concurrent.locks.ReentrantReadWriteLock;
  5. /**
  6. public class Test {
  7. public static void main(String[] args) {
  8. //创建并发访问的账户
  9. MyCount myCount = new MyCount("95599200901215522", 10000);
  10. //创建一个锁对象
  11. ReadWriteLock lock = new ReentrantReadWriteLock(false);
  12. //创建一个线程池
  13. ExecutorService pool = Executors.newFixedThreadPool(2);
  14. //创建一些并发访问用户,一个信用卡,存的存,取的取,好热闹啊
  15. User u1 = new User("张三", myCount, -4000, lock, false);
  16. User u2 = new User("张三他爹", myCount, 6000, lock, false);
  17. User u3 = new User("张三他弟", myCount, -8000, lock, false);
  18. User u4 = new User("张三", myCount, 800, lock, false);
  19. User u5 = new User("张三他爹", myCount, 0, lock, true);
  20. //在线程池中执行各个用户的操作
  21. pool.execute(u1);
  22. pool.execute(u2);
  23. pool.execute(u3);
  24. pool.execute(u4);
  25. pool.execute(u5);
  26. //关闭线程池
  27. pool.shutdown();
  28. }
  29. }
  30. /**
  31. class User implements Runnable {
  32. private String name; //用户名
  33. private MyCount myCount; //所要操作的账户
  34. private int iocash; //操作的金额,当然有正负之分了
  35. private ReadWriteLock myLock; //执行操作所需的锁对象
  36. private boolean ischeck; //是否查询
  37. User(String name, MyCount myCount, int iocash, ReadWriteLock myLock, boolean ischeck) {
  38. this.name = name;
  39. this.myCount = myCount;
  40. this.iocash = iocash;
  41. this.myLock = myLock;
  42. this.ischeck = ischeck;
  43. }
  44. public void run() {
  45. if (ischeck) {
  46. //获取读锁
  47. myLock.readLock().lock();
  48. System.out.println("读:" + name + "正在查询" + myCount + "账户,当前金额为" + myCount.getCash());
  49. //释放读锁
  50. myLock.readLock().unlock();
  51. } else {
  52. //获取写锁
  53. myLock.writeLock().lock();
  54. //执行现金业务
  55. System.out.println("写:" + name + "正在操作" + myCount + "账户,金额为" + iocash +",当前金额为" + myCount.getCash());
  56. myCount.setCash(myCount.getCash() + iocash);
  57. System.out.println("写:" + name + "操作" + myCount + "账户成功,金额为" + iocash +",当前金额为" + myCount.getCash());
  58. //释放写锁
  59. myLock.writeLock().unlock();
  60. }
  61. }
  62. }
  63. /**
  64. class MyCount {
  65. private String oid; //账号
  66. private int cash; //账户余额
  67. MyCount(String oid, int cash) {
  68. this.oid = oid;
  69. this.cash = cash;
  70. }
  71. public String getOid() {
  72. return oid;
  73. }
  74. public void setOid(String oid) {
  75. this.oid = oid;
  76. }
  77. public int getCash() {
  78. return cash;
  79. }
  80. public void setCash(int cash) {
  81. this.cash = cash;
  82. }
  83. @Override
  84. public String toString() {
  85. return "MyCount{" +
  86. "oid='" + oid + '\'' +
  87. ", cash=" + cash +
  88. '}';
  89. }
  90. }
  91. 写:张三正在操作MyCount{oid='95599200901215522', cash=10000}账户,金额为-4000,当前金额为10000
  92. 写:张三操作MyCount{oid='95599200901215522', cash=6000}账户成功,金额为-4000,当前金额为6000
  93. 写:张三他弟正在操作MyCount{oid='95599200901215522', cash=6000}账户,金额为-8000,当前金额为6000
  94. 写:张三他弟操作MyCount{oid='95599200901215522', cash=-2000}账户成功,金额为-8000,当前金额为-2000
  95. 写:张三正在操作MyCount{oid='95599200901215522', cash=-2000}账户,金额为800,当前金额为-2000
  96. 写:张三操作MyCount{oid='95599200901215522', cash=-1200}账户成功,金额为800,当前金额为-1200
  97. 读:张三他爹正在查询MyCount{oid='95599200901215522', cash=-1200}账户,当前金额为-1200
  98. 写:张三他爹正在操作MyCount{oid='95599200901215522', cash=-1200}账户,金额为6000,当前金额为-1200
  99. 写:张三他爹操作MyCount{oid='95599200901215522', cash=4800}账户成功,金额为6000,当前金额为4800
  100. Process finished with exit code 0



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

闽ICP备14008679号