3

我一直在利用 Java 的synchronized块来使我的部分代码线程安全。我正在将一个数据结构移植到通常可以使用synchronized块的 java,但我并不总是知道如何以典型的 Java 方式使用它们。

以下是一种场景的示例:

myMethod (Bool useLock)
    {
    if (useLock)
        {
        //locks the following section of code until unlocked.
        lockObject.lock();
        }

     //do more stuff....

    if (useLock)
        {
        //unlocks exclusive control of code.
        lockObject.unlock();
        }
     }

我如何在 Java 中做同样的事情?在这段代码中,有时我想锁定,有时我不想,但我想对它聪明一点,不必编写相同代码的两个版本。synchronized除了使用块之外,还有其他锁定 Java 的方法吗?

4

6 回答 6

7

您可以使用 Lock 对象,特别是ReentrantLock应该做的工作。http://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html

或者您仍然可以使用synchronized块来解决问题。您问题中的代码将如下所示:

myMethod (Bool useLock) {
    if (useLock) {
        synchronized (this) {
           criticalSection();
        }
    } else {
        criticalSection();
    }
}

criticalSection() {
   //do more stuff....
}

或者如果你想保证类的不同实例之间的互斥,你应该使用其他监视器对象而不是this. 例如TheClassName.class该类的实例或其他显式定义的静态变量。

于 2012-09-21T16:34:14.303 回答
3

已经发布了一些好的答案,但我想添加另一个对我有用的解决方案:

我开始:

...
synchronized(<lockobject>) {
 <huge section of code with lots of variables>
}
...

将其更改为:

...
synchronized(<condition> ? <lockobject> : new Object()) {
 <huge section of code with lots of variables>
}
...

基本上,如果条件为真,它使用 lockobject 上的同步来执行代码,但如果条件为假,它使用“new Object()”,这基本上让它在没有任何同步的情况下运行。

于 2014-07-30T19:23:40.540 回答
2

我猜ReentrantLock可以在你的场景中使用

final Lock lock = new ReentrantLock();

示例代码片段

class X {
private final ReentrantLock lock = new ReentrantLock();
 // ...

 public void m() { 
   lock.lock();  // block until condition holds
   try {
   // ... method body
   } finally {
   lock.unlock()
    }
  }
 }
于 2012-09-21T16:39:04.223 回答
1

您可以使用 Unsafe 来 monitorEnter 和 monitorExit 但恕我直言,这是一个坏主意。

如果不需要锁,JVM 无论如何都会将它们优化掉。synchronized如果只有一个线程获取它,则非常有效。(例如与 Lock 不同)

于 2012-09-21T16:26:21.033 回答
1

除了使用同步块之外,还有其他锁定 Java 的方法吗?

是的 - java.util.concurrent.locksReentrantLock尤其是类,但正如彼得所说,如果你能摆脱只使用synchronized它可能会更有效(并且更容易维护,特别是如果你作为一部分工作一个团队)。

于 2012-09-21T16:28:53.317 回答
1

您可以使用 Java锁定对象和条件对象。Conditionclass' java docs 也提供了一个很好的isFull例子isEmpty

在您的情况下,我想您可以利用条件对象使代码更具可读性/可理解性。像这样的东西:

 final Lock lock = new ReentrantLock();
 final Condition useLock  = lock.newCondition(); 

并酌情使用条件。

于 2012-09-21T16:40:37.387 回答