синхронизированный метод против синхронизированного блока - PullRequest
4 голосов
/ 27 мая 2011

Если у меня есть следующий код

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

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

Это будет синхронизировано с объектом this.
Однако, если моя главная цель здесь состоит в том, чтобы убедиться, что несколько потоков не используют methodA (или methodB) одновременно, но они МОГУТ одновременно использовать methodA AND methodB,
тогда такой дизайн ограничен? так как здесь thread1 блокирует объект (объект монитора, связанный с объектом) для запуска метода A, но в то же время поток 2 также ожидает блокировки объекта, даже если methodA и method B могут работать одновременно.
Это понимание правильно?

Если да, то это такая ситуация, когда мы используем синхронизированный блок для частного фиктивного объекта, чтобы methodA и methodB могли работать параллельно с другим потоком, но не methodA (или methodB) с другими потоками.
Благодарю.

Ответы [ 3 ]

9 голосов
/ 27 мая 2011

Вы сами ответили на вопрос: используйте один объект блокировки на метод, и вы в безопасности.

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

Для более продвинутых механизмов блокировки (например, ReentrantLock) читайте Параллелизм Java на практике , автор Brian Goetz et al. Вам также следует прочитать Effective Java от Josh Bloch , в нем также есть некоторые сведения об использовании synchronized.

2 голосов
/ 27 мая 2011

Если вы хотите разрешить одновременное выполнение 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) {
            // 
        }
    }
}
1 голос
/ 27 мая 2011

Если я правильно понимаю, вы хотите разрешить потоку T1 запускать methodA () одновременно с тем, что поток T2 выполняет methodB () - но вы не хотите, чтобы поток T1 запускал methodA () одновременно с потоком T2запускает methodA () (и то же самое для methodB), верно?Для этого сценария вы не можете использовать простой синхронизированный метод - вместо этого, как вы сказали, вам потребуется 2 фиктивных объекта (один для methodA и один для methodB) для синхронизации.Или вы можете использовать новый класс Lock - один экземпляр Lock на метод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...