三.多线程JUC篇-3.10 ReentrantLock

痛定思痛。 2022-12-20 06:10 280阅读 0赞

一.概念

  • ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁
  • 支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次获取不会被阻塞
    (1) 在线程获取锁的时候,如果已经获取锁的线程是当前线程的话则直接再次获取成功
    (2) 由于锁会被获取n次,那么只有锁在被释放同样的n次之后,该锁才算是完全释放成功
  • ReentrantLock还支持公平锁和非公平锁两种方式

二.与synchronized比较

  • ReentrantLock可以添加多个检控条件(condition),但是synchronized只可以添加一个
  • ReentrantLock可以控制得到锁的顺序(公平锁),也可以和synchronized一样使用非公平锁
  • ReentrantLock支持获取锁超时(tryLock()方法)以及获取锁响应中断的操作(lockInterruptibly()方法,synchronized不支持
  • -在高争用条件下,ReentarntLock的可伸缩性优于synchronized

三.何时应该使用ReentrantLock?

  • 在确实需要一些 synchronized 所没有的特性的时候,比如时间锁等候、可中断锁等候、无块结构锁、多个条件变量或者锁投票
  • ReentrantLock 还具有可伸缩性的好处,应当在高度争用的情况下使用它。但是请记住,大多数 synchronized 块几乎从来没有出现过争用,所以可以把高度争用放在一边
  • 我建议用 synchronized 开发,直到确实证明 synchronized 不合适,而不要仅仅是假设如果使用 ReentrantLock “性能会更好”
  • 请记住,这些是供高级用户使用的高级工具。(而且,真正的高级用户喜欢选择能够找到的最简单工具,直到他们认为简单的工具不适用为止。)一如既往,首先要把事情做好,然后再考虑是不是有必要做得更快

四.例子

  1. (1) 生产者代码:
  2. public class Producer implements Runnable {
  3. /** * 产品容器 */
  4. private List<Integer> container;
  5. private Lock lock;
  6. /** * 生产者条件 */
  7. private Condition producerCondition;
  8. /** * 消费者条件 */
  9. private Condition consumerCondition;
  10. public Producer(List<Integer> container, Lock lock, Condition producerCondition, Condition consumerCondition) {
  11. this.container = container;
  12. this.lock = lock;
  13. this.producerCondition = producerCondition;
  14. this.consumerCondition = consumerCondition;
  15. }
  16. public void produce() {
  17. //产品容器容量大小
  18. int capacity = 5;
  19. try {
  20. //获得锁
  21. lock.lock();
  22. //容器满了,不在生产
  23. if (container.size() == capacity) {
  24. System.out.println("生产满了。。。。");
  25. producerCondition.await();
  26. }
  27. Random random = new Random();
  28. int p = random.nextInt(50);
  29. //模拟1秒生产一个产品
  30. TimeUnit.MILLISECONDS.sleep(1000);
  31. System.out.println("生产产品:" + p);
  32. container.add(p);
  33. //生产一个产品,通知消费者
  34. consumerCondition.signal();
  35. } catch (InterruptedException e) {
  36. e.printStackTrace();
  37. } finally {
  38. //释放锁
  39. lock.unlock();
  40. }
  41. }
  42. @Override
  43. public void run() {
  44. while (true) {
  45. produce();
  46. }
  47. }
  48. }
  49.   
  50. (2) 消费者代码:
  51. public class Consumer implements Runnable{
  52. /** * 产品容器 */
  53. private List<Integer> container;
  54. private Lock lock;
  55. /** * 生产者条件 */
  56. private Condition producerCondition;
  57. /** * 消费者条件 */
  58. private Condition consumerCondition;
  59. public Consumer(List<Integer> container, Lock lock, Condition producerCondition, Condition consumerCondition) {
  60. this.container = container;
  61. this.lock = lock;
  62. this.producerCondition = producerCondition;
  63. this.consumerCondition = consumerCondition;
  64. }
  65. /** * 消费者消费产品 */
  66. private void consume(){
  67. try {
  68. //获得锁
  69. lock.lock();
  70. //容器大小为null,不消费
  71. if (container.size() == 0) {
  72. System.out.println("消费完了。。。。");
  73. consumerCondition.await();
  74. }
  75. Integer p = container.remove(0);
  76. //模拟1秒消费一个产品
  77. TimeUnit.MILLISECONDS.sleep(1000);
  78. System.out.println("消费产品:" + p);
  79. //消费了,通知生产者
  80. producerCondition.signal();
  81. } catch (InterruptedException e) {
  82. e.printStackTrace();
  83. } finally {
  84. //释放锁
  85. lock.unlock();
  86. }
  87. }
  88. @Override
  89. public void run() {
  90. while (true){
  91. consume();
  92. }
  93. }
  94. }
  95.   
  96. (3) 测试代码:
  97. public class ProducerConsumerTest {
  98. public static void main(String[] args) {
  99. List<Integer> container = new ArrayList<>();
  100. Lock lock = new ReentrantLock();
  101. Condition producerCondition = lock.newCondition();
  102. Condition consumerCondition = lock.newCondition();
  103. Thread producer = new Thread(new Producer(container,lock,producerCondition,consumerCondition));
  104. Thread consumer = new Thread(new Consumer(container,lock,producerCondition,consumerCondition));
  105. producer.start();
  106. consumer.start();
  107. }
  108. }
  109.   

发表评论

表情:
评论列表 (有 0 条评论,280人围观)

还没有评论,来说两句吧...

相关阅读