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

Дело 1

У меня есть 2 синхронизированных метода, как показано ниже:

class A {
    public void synchronized methodA() {}
    public void synchronized methodB() {}
}

A: У меня есть темы T1 и T2. Могут ли потоки одновременно выполнять methodA и methodB (соответственно), принадлежащие тому же экземпляру класса A?

  • Мой анализ: Ответ нет , поскольку потоком T1 будет выполняться только один метод, а поток T2 будет блокироваться до тех пор, пока T1 не завершит выполнение.

B: У меня есть темы T1 и T2. Могут ли потоки одновременно выполнять methodA и methodB (соответственно), принадлежащие различным экземплярам класса A?

  • Мой анализ: Ответ да , потому что T1 и T2 могут выполнять methodA и methodB, принадлежащие разным экземплярам класса A, и они не будут заблокированы.

Правильно ли мое понимание согласно моему анализу для случая 1?

Обновление: дело 2

У меня есть 2 синхронизированных метода, один не статический, а другой статический.

class A {        
    public void synchronized methodA() {}    
    public void static synchronized methodB() {}    
}       

A: У меня есть темы T1 и T2. Могут ли потоки одновременно выполнять methodA и methodB (соответственно), принадлежащие тому же экземпляру класса A?

  • Мой анализ: Ответ нет , потому что T1 будет выполнять только один метод, а T2 будет блокироваться до тех пор, пока T1 не завершит выполнение.

B: У меня есть темы T1 и T2. Могут ли потоки одновременно выполнять methodA и methodB (соответственно), принадлежащие различным экземплярам класса A?

  • Мой анализ: Ответ да , потому что T1 и T2 могут выполнять methodA и methodB, принадлежащие разным экземплярам, ​​и они не будут заблокированы.

Правильно ли мое понимание согласно моему анализу для случая 2?

Ответы [ 2 ]

4 голосов
/ 20 декабря 2010

Случай A: Нет

Случай B: Да

Ваш анализ верен.Синхронизированное ключевое слово в методе экземпляра функционально эквивалентно этому:

public void someMethod() {
   synchronized(this) {
      //code
   }
}

Поскольку this отличается в двух контекстах, они не являются взаимоисключающими.Обратите внимание, что даже один и тот же метод может быть вызван одновременно для двух разных экземпляров.

Редактировать

Для случая 2 вы неверны в 2A;это даже не имеет смысла.Статический синхронизированный метод не «принадлежит» экземпляру класса;если бы это было так, это не было бы статично!Он не синхронизируется с любым экземпляром класса (он не имеет ссылки на экземпляр для синхронизации!), Поэтому он синхронизируется с объектом класса A.Статический синхронизированный метод в классе A эквивалентен этому:

public static void methodB() {
   synchronized (A.class) {
      //code
   }
}

Ваш метод экземпляра будет синхронизироваться с экземпляром, как я показал выше, поэтому два потока могут работать параллельно.

Тогда, в случае B, очевидно, что они также могут работать параллельно, но вам все еще не хватает фундаментальной концепции, что статический метод не связан с любым экземпляром.

0 голосов
/ 20 декабря 2010

Случай 1: Вы правы.

Каждый объект Java имеет (среди прочего) связанную блокировку взаимного исключения (мьютекс). Когда synchronized применяется к нестатическому методу, блокируется мьютекс экземпляра. Таким образом, synchronized методы работают для каждого отдельного объекта.

Статические synchronized методы используют блокировку объекта Class, поэтому работают для каждого класса отдельно (по модулю ClassLoader) и независимо от нестатических методов. Вы также можете использовать synchronized() в теле метода, чтобы использовать блокировку любого объекта, который вы хотите.

Случай 2: Вы не правы, так как methodA () и methodB () используют разные мьютексы, как описано выше.

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