【问题标题】:ReeantrantLock and Condition variableReentrantLock 和 Condition 变量
【发布时间】:2016-01-18 17:11:01
【问题描述】:

你好:) 我正在学习 Java 中的重入锁和条件变量。我碰巧遇到了这个tutorial。在教程中,作者提供了一个利用 ReentrantLock 的 Producer-Consumer 示例:

public class CondDemo
{
   public static void main(String[] args)
   {
      Shared s = new Shared();
      new Producer(s).start();
      new Consumer(s).start();
   }
}

class Shared
{
   private volatile char c;
   private volatile boolean available;
   private final Lock lock;
   private final Condition condition;

   Shared()
   {
      c = '\u0000';
      available = false;
      lock = new ReentrantLock();
      condition = lock.newCondition();
   }

   Lock getLock()
   {
      return lock;
   }

   char getSharedChar()
   {
      lock.lock();
      try
      {
         while (!available) {
            try
            {
               condition.await();
            }
            catch (InterruptedException ie)
            {
               ie.printStackTrace();
            }
         }
         available = false;
         condition.signal();
      }
      finally
      {
         lock.unlock();
         return c;
      }
   }

   void setSharedChar(char c)
   {
      lock.lock();
      try
      {
         while (available) {
            try
            {
               condition.await();
            }
            catch (InterruptedException ie)
            {
               ie.printStackTrace();
            }
         }
         this.c = c;
         available = true;
         condition.signal();
      }
      finally
      {
         lock.unlock();
      }
   }
}

class Producer extends Thread
{
   private final Lock l;

   private final Shared s;

   Producer(Shared s)
   {
      this.s = s;
      l = s.getLock();
   }

   @Override
   public void run()
   {
      for (char ch = 'A'; ch <= 'Z'; ch++)
      {
         l.lock();
         s.setSharedChar(ch);
         System.out.println(ch + " produced by producer.");
         l.unlock();
      }
   }
}

class Consumer extends Thread
{
   private final Lock l;

   private final Shared s;

   Consumer(Shared s)
   {
      this.s = s;
      l = s.getLock();
   }

   @Override
   public void run()
   {
      char ch;
      do
      {
         l.lock();
         ch = s.getSharedChar();
         System.out.println(ch + " consumed by consumer.");
         l.unlock();
      }
      while (ch != 'Z');
   }
}

ProducerConsumer 中的 l.lock()l.unlock() 方法是不必要的吗?我注意到我们已经在Shared 对象的getSharedChar()setSharedChar() 方法中应用了锁定/解锁。或者这是使用条件变量的建议模式?

这是一个不好的做法,你能提供一个更好的例子的链接吗?

谢谢:)

【问题讨论】:

  • 嗯,很奇怪。阅读这段代码,在我看来,一个锁定的锁可以再次被锁定 - 这不应该抛出异常或其他什么吗?
  • 不,这是锁重入的基础。但是,当获得锁时,有count of acquisition 以确保在正确的位置完成锁释放。
  • 但是获得多个锁有什么好处呢?
  • 它可以让您设计不必依赖代码路径的功能。例如,您可以有一个公共方法 foo() 执行关键代码(因此需要锁定),然后它调用另一个公共方法 bar() 也执行关键操作。由于这两种方法都是公开的,因此没有简单的方法可以知道在哪个上下文中调用了 bar()。如果你在事务管理方面有一些经验,同样的逻辑也适用。您不知道您的交易是否绑定到您的方法或更高的调用者。但交易必须在其已打开的同一块级别发布。

标签: java multithreading reentrantlock


【解决方案1】:

这既不是必需的,也不是模式。

恕我直言,这是一个丑陋的冗余锁,曾经有干净的输出。我的意思是丑陋,因为没有 try-finally 来确保第一级解锁并且它暴露了Shared API 的内部状态。

要深入学习Java并发,你可以使用SynchronousQueueExchanger获得相同的结果

【讨论】:

  • 这没有提供问题的答案。要批评或要求作者澄清,请在其帖子下方发表评论。
  • 我已经说过这只是一个“喜剧”锁,所以既没有必要,也没有模式。我已明确添加我的答案。
  • 有没有更好的例子来说明如何使用 ReentrantLock 和 Condition 变量?
  • 你看过Condition documentation 吗?你也可以看看the official tutorial。我非常感谢Java Concurrent Animated。我没读过,但Concurrent Programming in JavaJava Concurrency in Practice 很有名
  • 此外,synchronized/wait/notify 的任何应用程序也适用。主要区别在于 Lock API 不是块绑定的(无论好坏),您可以通过使用多个 Condition 实例来拥有多个 wait/notify 组。
猜你喜欢
  • 1970-01-01
  • 2012-09-20
  • 2020-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-29
  • 2013-11-18
  • 1970-01-01
相关资源
最近更新 更多