我如何有条件地锁定Java?

时间:2012-09-21 16:23:46

标签: java locking synchronized

我一直在利用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的方法吗?

6 个答案:

答案 0 :(得分:5)

你可以使用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或该类的其他显式定义的静态变量。

答案 1 :(得分: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上使用synchronized执行代码,但如果条件为false,则使用“new Object()”,它基本上允许它在没有任何同步的情况下运行。

答案 2 :(得分: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()
    }
  }
 }

答案 3 :(得分:1)

你可以使用Unsafe来监控入口和monitorExit,但这是一个坏主意恕我直言。

如果不需要锁,JVM几乎可以在任何情况下优化它们。如果只有一个线程获得它,synchronized非常有效。 (例如,与Lock不同)

答案 4 :(得分:1)

  

除了使用synchronized块之外,还有其他方法可以锁定Java吗?

是 - java.util.concurrent.locks,特别是ReentrantLock课程,但正如彼得所说,如果你只是使用synchronized就可以逃脱它,那么整体效率可能更高(并且更容易维护,特别是如果您作为团队的一员工作)。

答案 5 :(得分:1)

您可以使用Java lock对象和Condition对象。 Condition类'java文档也提供了非常好的isFullisEmpty示例。

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

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

并适当使用该条件。