Вызов метода из синхронизированного метода

Я столкнулся со странной проблемой, которая заставила меня задуматься, что именно происходит в синхронизированном методе. Допустим, есть метод

synchronized public void example(){
     //...code
     int i=call(); //calling another method
     //...do something with i 
}

Теперь, пока выполняется метод call(), может ли другой объект войти в этот синхронизированный метод example()? Итак, когда call() возвращается, может быть какое-то ConcurrentModificationException? Что делать, чтобы избежать проблем?


person aps    schedule 05.08.2011    source источник
comment
Много лет спустя, но я думаю, что ReentrantReadWriteLock должен делать то, что вы надеетесь сделать.   -  person Hele    schedule 01.01.2015


Ответы (3)


Нет, не может. Синхронизированный метод в основном такой же, как:

public void example(){
  synchronized(this){
    //do stuff
  }
}
person Paweł Obrok    schedule 05.08.2011
comment
так что даже если я оставлю синхронизированный метод, а затем вернусь обратно, это будет похоже на один большой синхронизированный метод? Вызовы внешних методов не вызовут проблем? - person aps; 05.08.2011
comment
Причина, по которой я пытаюсь быть уверенным, заключается в том, что проблема в моей программе, вероятно, связана с какой-то другой вещью, которую я должен выяснить. Спасибо. - person aps; 05.08.2011
comment
Нет, они не вызывают никаких проблем. Если бы они были, что бы вы могли сделать в синхронизированном блоке? Любая осмысленная задача включает в себя вызов какого-либо метода. - person JB Nizet; 05.08.2011
comment
@aps Несмотря на то, что метод synchronized, на самом деле происходит то, что монитор вызывающего объекта запускается при запуске метода, а затем закрывается при возврате метода. Что бы ни происходило между этими двумя точками, это не влияет на состояние монитора, поэтому даже внешние методы не повлияют на него. - person dlev; 06.08.2011

Обратите внимание, что в этом примере, если call() не является закрытым или вызывается из другого места в классе, кто-то другой может прервать то, что вы считаете полностью синхронным процессом.

synchronized void a(){
    println 'hello'
    b();
    println 'world'
}

void b(){

}

Если вы ожидаете, что «все, что делает a, будет защищено синхронизацией», то, если b вообще имеет какие-либо побочные эффекты, эта гарантия теряется, если методы, отличные от synchronized void a, вызывают b.

person Stefan Kendall    schedule 05.08.2011
comment
Я понял вашу точку зрения, что мне делать в таком случае? сделать b синхронизированным, чтобы не было прерываний? - person aps; 06.08.2011
comment
Если b вызывается только из a, все в порядке. В целях безопасности любой метод точки входа (общедоступный, защищенный, используемый по умолчанию) в класс может быть синхронизирован. Таким образом, вы фактически гарантируете, что только один поток может использовать объект одновременно. Также убедитесь, что вы не манипулируете общедоступными, защищенными переменными или переменными по умолчанию напрямую, так как вы можете попасть в шланг точно так же, как при настройке метода. - person Stefan Kendall; 06.08.2011
comment
Для очень подробного и зубодробительного рассмотрения темы ознакомьтесь с учебным пособием SCJP 6. amazon.com/SCJP-Certified-Programmer-Java-310- 065/дп/0071591060 - person Stefan Kendall; 06.08.2011
comment
@Greg: Я вижу, что вы троллите мои ответы отрицательными голосами, и автоматический аудитор обмена стеками тоже будет. - person Stefan Kendall; 19.08.2011
comment
Вряд ли это будет троллингом, если я предложу ДЕЙСТВИТЕЛЬНОЕ объяснение каждому минусу. Вы не можете отрицать, что код здесь неверен и даже не пытается использовать правильный синтаксис. - person GBa; 19.08.2011
comment
Я вижу, вы не знакомы с другими языками на основе JVM или прототипированием любого рода. - person Stefan Kendall; 19.08.2011

Когда поток входит в синхронизированный метод, возникает блокировка, блокировка не снимается до тех пор, пока этот метод не вернется, что произойдет после вашего вызова call().

Вот хорошая статья о блокировках и синхронизации: http://download.oracle.com/javase/tutorial/essential/concurrency/locksync.html

person Hunter McMillen    schedule 05.08.2011