У меня небольшие разногласия по поводу происходит до в Java и синхронизации.
Представьте себе следующий сценарий:
Основная тема
MyObject o = new MyObject(); // (0)
synchronized (sharedMonitor) {
// (1) add the object to a shared collection
}
// (2) spawn other threads
Другие темы
MyObject o;
synchronized (sharedMonitor) {
// (3) retrieve the previously added object
}
// (4) actions to modify the object
Обратите внимание, что переменные экземпляра MyObject
не являются ни volatile
, ни final
. Методы MyObject
не используют синхронизацию.
Насколько я понимаю, это:
1 происходит до 3, так как синхронизация происходит на том же мониторе, а другие потоки создаются только на 2 >, который выполняется после 1.
Действия на 4 не гарантируют того, что позже они будут видны основному потоку, если не будет дальнейшей синхронизации для всех потоков, и основной поток каким-то образом синхронизируется после этих действий.
Вопрос. Есть ли какие-либо гарантии того, что действия с номером 0 будут видны, что они будут выполняться до, а также будут иметь одновременный доступ на 3, или я должен объявить переменные как volatile
?
Рассмотрим теперь следующий сценарий:
Основная тема
MyObject o = new MyObject(); // (0)
synchronized (sharedMonitor) {
// (1) add the object to a shared collection
}
// (2) spawn other threads, and wait for their termination
// (5) access the data stored in my object.
Другие темы
MyObject o;
synchronized (sharedMonitor) {
// (3) retrieve the previously added object
}
o.lock(); // using ReentrantLock
try {
// (4) actions to modify the object
} finally { o.unlock(); }
Насколько я понимаю, это:
1 происходит до 3, как и прежде.
Действия в 4 видны между другими потоками из-за синхронизации в
ReentrantLock
, удерживаемойMyObject
.Действия над 4 логически происходят после 3, но нет связи происходит до от 3 до 4. вследствие синхронизации на другом мониторе.
Пункт выше останется верным, даже если была синхронизация
sharedMonitor
послеunlock
из 4.Действия над 4 не происходят до доступа к 5, даже если основной поток ожидает завершения других задач. Это связано с тем, что доступ к 5 не синхронизирован с
o.lock()
, поэтому основной поток может по-прежнему видеть устаревшие данные.
Вопрос. Правильно ли я понимаю?