Вложенное синхронизированное ключевое слово
У меня есть этот код в Java:
public void doSomeThing() {
synchronized (this) {
doSomeThingElse();
}
}
public void doSomeThingElse() {
synchronized (this) {
// do something else
}
}
Может ли этот кодовый блок? Я имею в виду, может ли этот код ждать навсегда?
Ответы
Ответ 1
Как описывает java-документация для блокировки реентера:
поток может получить блокировку, чтобы она уже владеет
Второй синхронизированный блок использует один и тот же замок и поэтому всегда будет использоваться, поскольку блокировка уже была приобретена внешним методом.
Нет, тупика не будет.
Ответ 2
Если поток владеет блокировкой на this
, он перейдет в другие методы synchronized
/блок, например, горячий нож в масле.
Ответ 3
В синхронизированном блоке вы можете повторно использовать блокировку, которой у вас уже есть. Поставщик блокировки (этот) будет получен первым потоком для ввода doSomething(). Затем в методе doSomethingElse() он повторно загрузит его.
Причина для этого? Ну, нечего сказать, что нет другого потока, входящего в doSomethingElse из другого места. Это предотвратит выполнение любым кодом кода в doSomething(), пока поток в doSomethingElse() не выпустит "this".
Изменить Кстати, он может, конечно, блокировать... и блокирует любой поток, которому не принадлежит объект синхронизации от выполнения. Однако он не будет (как указано) тупиком.
Ответ 4
Заблокировать уже obtanied потоком, выполняющим метод doSomething, поэтому этот поток может выполнить метод doSomethingElse.
Для создания ситуации взаимоблокировки требуется два объекта блокировки. В вашем случае есть только один, поэтому невозможно создать тупик.
Ответ 5
Синхронизированное использование в обоих случаях this
, поэтому, если синхронизированный блок в doSomeThing выполняется, у вас уже есть блокировка, чтобы вы могли выполнить метод doSomeThingElse.
Если ваш код настолько прост, он эквивалентен:
public synchronized void doSomeThing() {
doSomeThingElse();
}
public synchronized void doSomeThingElse() {
// do something else
}
Ответ 6
Вы уже сделали блокировку монитора в первом синхронизированном состоянии.
Вы всегда должны убедиться, что дизайн concurrency не сильно влияет на производительность.
Один из способов обеспечить это путем синхронизации только необходимых операторов/кода.
Скажем, теперь ваш код будет выглядеть примерно так.
public void doSomeThing()
{
synchronized (this)
{
synchronized (this)
{
// do something else
}
}
}
В то время как это то, что требуется
public void doSomeThing()
{
doSomeThingElse();
}
public void doSomeThingElse()
{
synchronized (this)
{
// do something else
}
}