【发布时间】: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');
}
}
Producer 和 Consumer 中的 l.lock() 和 l.unlock() 方法是不必要的吗?我注意到我们已经在Shared 对象的getSharedChar() 和setSharedChar() 方法中应用了锁定/解锁。或者这是使用条件变量的建议模式?
这是一个不好的做法,你能提供一个更好的例子的链接吗?
谢谢:)
【问题讨论】:
-
嗯,很奇怪。阅读这段代码,在我看来,一个锁定的锁可以再次被锁定 - 这不应该抛出异常或其他什么吗?
-
不,这是锁重入的基础。但是,当获得锁时,有count of acquisition 以确保在正确的位置完成锁释放。
-
但是获得多个锁有什么好处呢?
-
它可以让您设计不必依赖代码路径的功能。例如,您可以有一个公共方法
foo()执行关键代码(因此需要锁定),然后它调用另一个公共方法bar()也执行关键操作。由于这两种方法都是公开的,因此没有简单的方法可以知道在哪个上下文中调用了bar()。如果你在事务管理方面有一些经验,同样的逻辑也适用。您不知道您的交易是否绑定到您的方法或更高的调用者。但交易必须在其已打开的同一块级别发布。
标签: java multithreading reentrantlock