【问题标题】:synchronized method vs synchronized block同步方法与同步块
【发布时间】:2011-05-27 09:54:42
【问题描述】:

如果我有以下代码

class SomeClass {    
...
public synchronized methodA() {
....
}

public synchronized methodB(){
....
}
}

这将在“this”对象上同步。
但是,如果我在这里的主要目标是确保多个线程不会同时使用方法 A(或方法 B),但它们可以同时使用方法 A 和方法 B,
那么这种设计有限制吗?因为这里 thread1 锁定对象(与对象关联的监视对象)以运行 methodA 但同时 thread2 也在等待对象锁定,即使 methodA 和 methodB 可以同时运行。
这种理解正确吗?

如果是,这是我们在私有虚拟对象上使用同步块的情况,以便方法A和方法B可以与不同的线程并行运行,但不能与不同的线程并行运行方法A(或方法B)。
谢谢。

【问题讨论】:

标签: java concurrency


【解决方案1】:

你自己已经回答了这个问题:每个方法使用一个锁对象,你是安全的。

private final Object lockA = new Object();
private final Object lockB = new Object();
public void methodA() {
    synchronized(lockA){
        ....
    }
}
public void methodB() {
    synchronized(lockB){
        ....
    }
}

有关更高级的锁定机制(例如 ReentrantLock),请阅读 Brian Goetz 等人的 Java Concurrency in Practice。您还应该阅读Effective Java by Josh Bloch,它还包含一些关于使用synchronized的项目。

【讨论】:

  • 并将lockAlockB 设为final 字段。
【解决方案2】:

如果您希望允许同时运行methodA()methodB(),但又将每个方法限制为一个线程,那么您需要两个单独的对象进行同步。例如:

class SomeClass {
    private final Object lockA = new Object();
    private final Object lockB = new Object();

    public void methodA() {
        synchronized (lockA) {
            // 
        }
    }

    public void methodB() {
        synchronized (lockB) {
            // 
        }
    }
}

【讨论】:

    【解决方案3】:

    如果我的理解是正确的,您希望允许线程 T1 在线程 T2 运行 methodB() 的同时运行 methodA() - 但您不希望线程 T1 在线程 T2 的同时运行 methodA()运行methodA()(和methodB相同)对吗? 对于这种情况,您不能只使用简单的同步方法——相反,正如您所说,您将需要 2 个虚拟对象(一个用于方法 A,一个用于方法 B)进行同步。或者您可以使用新的 Lock 类——每个方法一个 Lock 实例。

    【讨论】:

    • 然后你可以使用上面显示的方法之一,或者像我说的那样看看 java.util.concurrent.locks.ReentrantLock 。
    最近更新 更多