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