2013-08-21 2 views
32

Попытка визуализации и понимания синхронизация.Статический и нестатический объект блокировки в синхронизированном блоке

  1. Каковы различия между использованием статического объекта блокировки (код A) и нестатический блокировки объекта (Код B) для синхронизированных блока?
  2. Как он отличается в практических приложениях?
  3. Каковы подводные камни, которые у других не было бы?
  4. Каковы критерии для определения, какой из них использовать?

Код

public class MyClass1 { 
    private static final Object lock = new Object(); 
    public MyClass1() { 
    //unsync 
    synchronized(lock) { 
     //sync 
    } 
    //unsync 
    } 
} 

Код B

public class MyClass2 { 
    private final Object lock = new Object(); 
    public MyClass2() { 
    //unsync 
    synchronized(lock) { 
     //sync 
    } 
    //unsync 
    } 
} 

Примечание

Приведенный выше код показывает, конструкторами, но вы могли бы говорить о том, как бэха vior отличается в статическом методе и нестационарном методе. Кроме того, было бы целесообразно использовать статический замок, когда синхронизированный блок модифицирует статическую переменную-член?

Я уже смотрел ответы в this question, но недостаточно ясно, что представляют собой различные сценарии использования.

+2

«Обратите внимание, что приведенный выше код показывает конструкторы:« Это важное различие. Синхронизированный блок с полем экземпляра в конструкторе абсолютно бессмысленен, поскольку ни один из двух потоков никогда не будет выполнять конструктор в одном экземпляре. – Thilo

+0

Собственно, подумайте об этом, это поле экземпляра может содержать объект, общий для потоков. Например, 'private final Object lock =" niceLiteralString ";'. – Thilo

+0

Я понимаю использование конструкторов, чтобы показать пример, была плохая идея. Мой вопрос распространяется и на статические и нестатические методы. Кроме того, как распределение статического/экземпляра влияет на блокировку? – ADTC

ответ

42

Разница проста: если запертой на объект находится в static поле, то все экземпляры MyClass* будут доли что блокировка (т.е. нет двух объектов не будет в состоянии зафиксировать на этом объекте в то же время) ,

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

При использовании статического объекта блокировки:

  • нити 1 звонки o1.foo()
  • нить 2 вызовов o1.foo(), придется ждать потока 1, чтобы закончить
  • нити 3 вызова o2.foo(), будет также необходимо подождать нить 1 (и, вероятно, 2) до конца

Когда y НУ использовать не статический объект блокировки:

  • нить 1 звонки o1.foo()
  • нить 2 вызовы o1.foo(), придется ждать потока 1, чтобы закончить
  • нить 3 вызова o2.foo(), он может просто продолжать, не обращая внимания нить 1 и 2

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

Как правило, вы хотите, чтобы объект блокировки имел то же значение static, что и значение, оперированное при включении. Поэтому, если вы управляете нестатическими значениями только, вам понадобится объект нестатического блокирования. Если вы управляете статическими значениями только, вам понадобится статический объект блокировки.

Когда вы манипулируете статическими и нестационарными значениями, тогда это станет сложным. Метод easy - это просто использовать объект статической блокировки, но это может увеличить размер синхронизированного блока более чем абсолютно необходимо и, возможно, потребуется больше блокировки, чем хотелось бы. В таких случаях вам может потребоваться сочетание статических и нестатических объектов блокировки.

В вашем конкретном случае вы используете блокировку в конструкторе, которая будет выполняться только один раз на каждый экземпляр, поэтому нестатический блокирующий объект здесь не имеет никакого смысла.

+1

Я думаю, что использование конструктора в качестве примера было плохой идеей. Во всяком случае, хороший ответ. Я хочу задать еще один вопрос.Есть ли способ убедиться, что набор методов, работающих с переменной ** volatile static ** member variable через один поток, будет _done и over with_ до того, как другие потоки обратятся к этой переменной-члену? Я могу сделать это отдельным вопросом о SO, если это необходимо. – ADTC

+0

@ ADTC: это звучит как отдельный вопрос для меня. Короткий ответ: нет, вам понадобится синхронизация. Вы можете избежать этого, только если операция волатильности равна * atomic * (например, один '++' на 'int' ** и ** вам не нужен порядок (т. Е. Вам все равно, если вы читаете до или после операции). –

+0

Мне очень нравится чтение, это должно произойти только после операции. Я думаю, что я задам этот вопрос как отдельный вопрос. – ADTC

Смежные вопросы