1

Я правильно понял, что при отсутствии другой синхронизации потоков, все доступ к совместно используемому изменяемому состоянию должны использовать некоторую форму безопасности нижнего уровня (например, барьеры памяти), чтобы избежать операции реорганизация (будь то через компилятор, JIT или CPU)?Неустойчивый доступ к общему разрешенному состоянию

Например, на C# я должен использовать Volatile.Read (ref someVar) и Volatile.Write (ref someVar, someValue) везде, где я не использую какую-либо другую синхронизацию?

У меня такое ощущение, что ответ да, я должен. Но это кажется ... Чрезмерным.


записку, прежде чем кто встревает: Я не говорю о безопасности потоков или параллелизм здесь; просто согласованность памяти. Я хорошо знаю, что согласованность памяти не является единственной проблемой при написании многопоточного кода.

ответ

1

Прежде всего, если вы объявляете переменные volatile, вы можете просто читать/записывать их нормально и получать помехи памяти.

Актуальный вопрос: Зависит от того, как вы определяете «согласованность памяти». В зависимости от вашего случая использования вы не должны синхронизировать все записи/чтения, вы можете получить с помощью всего одного одного, чтобы убедиться, что несколько вещей, которые публикуются сразу:

// T1: 
foo = 5 // non-volatile 
bar = 7 // non-volatile 
done = True // volatile write 

// T2: 
if (done) { // volatile read 
    foo and bar guaranteed to be 5, respectively 7 with non-volatile reads 
} 

Но да вам все еще нужно, по крайней мере что один барьер памяти на поток в противном случае ваш код будет «неисправным». Но тогда это зависит от того, как вы определяете «неисправность».

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

+0

Отличный ответ, спасибо. – Xenoprimate

Смежные вопросы