VB.NET: нужно ли мне вызывать Thread.MemoryBarrier() перед каждым чтением, если я всегда завершаю запись с помощью Thread.MemoryBarrier()?

VB.Net не имеет эквивалента ключевого слова C# volatile, поэтому вам нужно вручную реализовать volatile, что обычно делается путем вызова Thread.MemoryBarrier() перед чтением и после записи. Так что что-то вроде этого эквивалентно объявлению volatile переменной C#:

    ''' <summary>
    ''' Gets a value indicating whether this instance is disposed.
    ''' </summary>
    Public Property IsDisposed As Boolean
        Get
            Threading.Thread.MemoryBarrier()
            Return _isDisposed
        End Get
        Private Set(value As Boolean)
            _isDisposed = value
            Threading.Thread.MemoryBarrier()
        End Set
    End Property

Мне интересно, нужен ли барьер памяти перед чтением, если единственное место, где я пишу переменную, - это сеттер, и там я всегда вызываю Thread.MemoryBarrier() после записи.

Могу ли я безопасно удалить Thread.MemoryBarrier() перед чтением?

Редактировать: Чтобы сделать это более ясным, я спрашиваю, могу ли я удалить Thread.MemoryBarrier() перед чтением, чтобы удалить затраты на забор памяти для каждого чтения.


person Dalibor Čarapić    schedule 14.01.2015    source источник
comment
Класс Volatile должен работать в VB.net, а класс Thread содержит такие методы, как VolatileRead   -  person CodesInChaos    schedule 14.01.2015
comment
Вопрос в том, могу ли я безопасно удалить Thread.MemoryBarrier() перед чтением, чтобы избежать потенциально ненужных затрат на забор памяти при чтении.   -  person Dalibor Čarapić    schedule 14.01.2015
comment
Я почти уверен, что вы можете получить устаревшие чтения, если удалите его.   -  person CodesInChaos    schedule 14.01.2015
comment
Вы не можете удалить его. Кстати, маловероятно, что вы используете его правильно, когда задаете этот вопрос. Прочитайте это.   -  person Hans Passant    schedule 14.01.2015
comment
Тогда интернет немного противоречив. См.: albahari.com/threading/part4.aspx (отрывок: статический Методы VolatileRead и VolatileWrite в классе Thread читают/записывают переменную, применяя (технически, расширенный набор) гарантий, предоставляемых ключевым словом volatile.Однако их реализации относительно неэффективны, поскольку они фактически генерируют полные ограничения)   -  person Dalibor Čarapić    schedule 14.01.2015


Ответы (1)


Вы не можете удалить барьер на стороне чтения, что легко показать на примере. Давайте использовать этот читатель:

while (!IsDisposed); //reads _isDisposed

Очевидно, что значение _isDisposed может кэшироваться в регистре здесь, чтобы новые записи никогда не становились видимыми. Этот цикл может быть бесконечным (например, возможны другие эффекты, такие как длительные задержки).

Более формально, все операции чтения _isDisposed могут перемещаться «вверх» во времени, чтобы казалось, что они выполняются до того, как произойдет сохранение. volatile хранилища создают барьер освобождения, что означает, что ничто не может переместиться через них позже во времени. Однако вещи могут перемещаться по ним в предыдущие моменты времени.

Используйте класс Volatile. Или используйте структуру, написанную на C#, в качестве оболочки поля:

struct VolatileInt32Box { public volatile int Value; }
person usr    schedule 14.01.2015
comment
Я буду использовать решение VolatileRead/VolatileWrite, предложенное Хансом Пассантом. - person Dalibor Čarapić; 14.01.2015
comment
@dcarapic по какой-то причине эти два метода намного медленнее. Они компилируются в вызовы методов. У них одни недостатки. - person usr; 14.01.2015
comment
Не согласно Гансу Пасанту (ссылка, которую он предоставил stackoverflow.com/questions/27468923/). Теперь я не проверял это, но я читал из других источников, что ключевое слово C # volatile и VolatileWrite/VolatileRead должны быть схожими по функциональности и скорости. - person Dalibor Čarapić; 14.01.2015
comment
Я протестировал это несколько дней назад на текущем 4.5 JIT и RyuJIT следующего поколения. RyuJIT генерирует хороший код, текущий JIT продолжает разочаровывать. Не обращая внимания на производительность, я рекомендую: Используйте более новую функциональность (класс Volatile). - person usr; 14.01.2015