Java用不同的方法锁定和解锁。如何尝试/终于?

时间:2016-11-16 09:40:08

标签: java multithreading concurrency locking

我正在试图找出使用带锁的try / finally的最佳方法。

当我在同一个地方lock()unlock()时,我只是使用try/finally块,因为JavaDoc也建议:

lock.lock();
try{
  // do something
} finally {
  lock.unlock();
}

我想知道try/finallylock()调用在不同的方法中时使用unlock()的最佳做法是什么。

例如,请考虑以下事项:

public class X {
  private ReentrantLock lock = new ReentrantLock();

  public void pickUp(){
    lock.lock();
    // do something
  }

  public void putDown(){
    // do something
    lock.unlock();
  }
}

我要做的是将try/finally块放在上层,即每当我调用方法pickUp()putDown()时。例如,在run()方法内部:

// class code
X x = new X();

public void run(){
  try{
    x.pickUp();
    // do something
  } finally {
    x.putDown();
  }
}

这是正确的方法吗?

非常感谢。

1 个答案:

答案 0 :(得分:1)

这实际上是应用execute around method pattern的非常好的候选人。

如果您的类的客户端需要对需要正确初始化和/或正确清理的资源执行某些操作,您可以将清理保留在客户端的手中,并希望文档和失败的快速行为将客户端推入妥善处理资源。

执行周围的方法模式delas与此难题通过再次初始化和清除客户端的手。基本上,您引入了一种方法,可以正确地执行资源的初始化和清理,并在之间将其移交给该资源的Consumer

理想情况下,您甚至可以完全封装执行初始化和清理的方法。

例如,根据您的示例代码:

private ReentrantLock lock = new ReentrantLock();

private void pickUp() { // now private
  lock.lock();
  // do something
}

private void putDown() { // now private
  // do something
  lock.unlock();
}

public void use(Consumer<X> consumer) {
  try {
    pickUp();
    consumer.accept(this);  // client gets its hands on the properly initialized resource.
  } finally {
    putDown();
  }
}

客户端仍然可以对资源进行混乱处理,例如在清理后在消费者之外使用它,但这已经很难了。记住正确的初始化和清理工作的困难部分不再是客户关注的问题。