Синхронизация дважды на одном и том же объекте гарантирует, что все изменения, сделанные во внутреннем блоке, сбрасываются в общую память при выходе из внутреннего блока синхронизации. Но важно отметить, что нет правил, согласно которым изменения, внесенные после внутреннего блока синхронизации, не могут быть выполнены до завершения внутренней синхронизации.
Например
public void doSomething()
{
synchronized(this) { // "this" locked
methodCall1();
synchronized(this) {
methodCall2();
} // memory flushed
methodCall3();
} // "this" unlocked and memory flushed
}
Может быть скомпилировано для выполнения в этом порядке
public void doSomething()
{
synchronized(this) { // "this" locked
methodCall1();
synchronized(this) {
methodCall2();
methodCall3();
} // memory flushed
} // "this" unlocked and memory flushed
}
Для более подробного объяснения посмотрите Двойная проверка блокировки в Исправление, которое не работает раздел примерно на треть пути вниз.