Java meomry образцовые мандаты это synchronize
блоки, которые синхронизируются на том же мониторе, осуществляют before-after-realtion на переменных, измененных в тех блоках. Пример:
// in thread A
synchronized( lock )
{
x = true;
}
// in thread B
synchronized( lock )
{
System.out.println( x );
}
В этом случае гарантировано, что поток B будет видеть x==true
пока уже распараллеливают переданный это synchronized
- блок. Теперь я нахожусь в процессе для перезаписи большого количества кода для использования более гибкого (и сказанный быть быстрее) привязывается java.util.concurrent
, особенно ReentrantReadWriteLock
. Таким образом, пример похож на это:
Править: Пример был поврежден, потому что я неправильно преобразовал код, как отмечено матовым b. Зафиксированный следующим образом:
// in thread A
lock.writeLock().lock();
{
x = true;
}
lock.writeLock().unlock();
// in thread B
lock.readLock().lock();
{
System.out.println( x );
}
lock.readLock().unlock();
Однако я не видел подсказок в спецификации модели памяти, что такие блокировки также подразумевают упорядочивание nessessary. При изучении реализации это, кажется, полагается на доступ к энергозависимым переменным внутри AbstractQueuedSynchronizer
(для реализации солнца, по крайней мере). Однако это не часть никакой спецификации, и кроме того доступ к энергонезависимым переменным не действительно condsidered покрыт барьером памяти, данным этими переменными, не так ли?
Так, вот мои вопросы:
synchronized
блоки?С уважением, Steffen
--
Комментарий к Yanamon:
Взгляд на следующий код:
// in thread a
x = 1;
synchronized ( a ) { y = 2; }
z = 3;
// in thread b
System.out.println( x );
synchronized ( a ) { System.out.println( y ); }
System.out.println( z );
Из того, что я понял, барьер памяти осуществляет второй вывод для показа 2, но не гарантировал влияние на других переменных...? Таким образом, как это может сравниться с доступом к энергозависимой переменной?
Из API-документа :
Все реализации блокировки должны обеспечивать одинаковую синхронизацию памяти Семантика , обеспечиваемая встроенной блокировкой монитора , как описано в Спецификации языка Java, третье издание (модель памяти 17.4):
* Успешная операция блокировки имеет те же эффекты синхронизации памяти, что и успешное действие Lock. * Успешная операция разблокировки имеет те же эффекты синхронизации памяти, что и успешное действие Unlock.
Неудачная блокировка и операции разблокировки и операции повторного входа блокировки / разблокировки не требуют каких-либо эффектов синхронизации памяти .
Чтение и запись энергозависимых переменных теперь принудительно происходит до и после упорядочивания операций. Запись в изменчивую переменную имеет тот же эффект, что и отключение монитора, а чтение переменной имеет эффект, как получение монитора. Следующий пример делает это немного более ясным:
volatile boolean memoryBarrier = false;
int unguardedValue = 0;
//thread a:
unguardedValue = 10;
memoryBarrier = true;
// thread b
if (memoryBarrier) {
// unguardedValue is guaranteed to be read as 10;
}
Но все, что было сказано, предоставленный вами пример кода не выглядел так, как будто он действительно использовал ReentrantLock
, поскольку он был разработан для использования.
Lock
встроенного в Java ключевого слова syncronized
фактически делает доступ к блокировке уже однопоточным, поэтому он не дает Lock
шанс выполнить любую реальную работу.
должно выполняться в соответствии с приведенным ниже шаблоном, это описано в документации Java Lock
lock.readLock().lock();
try {
// Do work
} finally {
lock.readLock.unlock();
}
Помимо вопроса о том, что гарантирует семантика модели памяти, я думаю, что есть несколько проблем с кодом, который вы публикуете.
Lock
вам не нужно использовать блок synchronized
. Lock
- это делать это в блоке try-finally, чтобы предотвратить случайное снятие блокировки (поскольку блокировка не снимается автоматически при входе в любой блок, в котором вы находитесь, поскольку с синхронизированным блоком
). Вы должны использовать блокировку
примерно так:
lock.lock();
try {
//do stuff
}
finally {
lock.unlock();
}