Многопоточность.NET - я должен синхронизировать доступ к переменной типа примитива?

победа: как насчет StackWalk64 http://msdn.microsoft.com/en-us/library/ms680650.aspx

7
задан Neil Barnwell 11 August 2009 в 10:14
поделиться

9 ответов

Чтения примитивных типов являются атомарными при условии, что они соответствуют чтению ЦП. Таким образом, чтение 32-битного примитивного типа является атомарным на 32-битном ЦП, тогда как чтение 64-битного типа - нет. Однако, если он также не является изменчивым , другой ваш поток может не видеть изменений из-за кэширования.

6
ответ дан 6 December 2019 в 11:51
поделиться

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

3
ответ дан 6 December 2019 в 11:51
поделиться

Если один поток считывает значение, а другой поток записывает значение, в этом случае это безопасно, но обратите внимание на объявление свойства Enabled с ключевым словом volatile, чтобы быть уверенным, что значение будет синхронизируется со всеми процессорами, если вы работаете с двухъядерным компьютером.

3
ответ дан 6 December 2019 в 11:51
поделиться

Как уже было сказано правильно, можно использовать volatile (или блокировку для переменной) для доступа к значению переменной потокобезопасным способом. .

Не делая переменную изменчивой , компилятор может применить методы оптимизации, которые изменяют порядок команд, что может привести к неожиданным и непредсказуемым результатам.

В соответствующей части спецификации языка C # ( 10.4.3 Volatile fields ) далее говорится:

Для изменчивых полей такое переупорядочение оптимизации ограничены:

  • Чтение изменчивого поля называется изменчивым чтением. Неустойчивый read имеет "приобретать семантику"; то есть, это гарантированно произойдет до любого ссылки на память, возникающие после это в последовательности команд.
  • Запись энергозависимого поля называется энергозависимой записью. Неустойчивый write имеет «семантику выпуска»; который есть, это гарантированно произойдет после любые ссылки на память до напишите инструкцию в инструкцию последовательность.

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

  • ссылочный тип.
  • Тип байт , sbyte , короткий , ushort , int , uint , char , float или bool .
  • enum -тип, имеющий базовый тип enum byte, sbyte, short, ushort, int или uint.
3
ответ дан 6 December 2019 в 11:51
поделиться

Если вы не отметили его как энергозависимый, он будет работать на однопроцессорных компьютерах (из-за 32-битной атомарности), но не на ПК с несколькими процессорами, так как он будет хранить значение на своем кристалле. cache и не извлекать самое последнее значение, поэтому вам нужно пометить Volatile. Это правда, что вам не нужно блокировать элементы, если их размер 32 бита, поскольку это всего лишь изменение размера реестра и, следовательно, атомарно.

Здесь есть статья об этом: www.yoda.arachsys.com/csharp /threads/volatility.shtml

Существует также нечто, называемое Домены синхронизации .

Домен синхронизации обеспечивает автоматическую декларативную синхронизацию доступа потоков к объектам. Этот класс был представлен как часть инфраструктуры, поддерживающей удаленное взаимодействие .NET. Разработчики, желающие указать, что класс должен иметь доступ к своим синхронизированным объектам, должны иметь класс, унаследованный от ContextBoundObject, и пометить его атрибутом SynchronizationAttribute следующим образом:

[Synchronization]
public class MyController : ContextBoundObject 
{
  /// All access to objects of this type will be intercepted
  /// and a check will be performed that no other threads
  /// are currently in this object's synchronization domain.
}

Дополнительную информацию о доменах синхронизации можно найти здесь: msdn.microsoft .com / en-us / magazine / dd569749.aspx

1
ответ дан 6 December 2019 в 11:51
поделиться

Если вы не используете volatile или не заблокируете логическое значение, оно будет работать на x86. Однако он может не работать на процессорах Intel Itanium (IA64). Вот хорошая статья в формате kb , которая все объясняет.

1
ответ дан 6 December 2019 в 11:51
поделиться

Вы можете использовать Interlocked.Exchange в этом случае, если вас беспокоит некрасивая блокировка.

0
ответ дан 6 December 2019 в 11:51
поделиться

Существует пример MSDN , который точно описывает, что вы делаете: Как: создавать и завершать потоки (Руководство по программированию на C #) . Он предполагает, что вам нужно объявить свое свойство Enabled как volatile и не нужно заблокировать его.

0
ответ дан 6 December 2019 в 11:51
поделиться

Вы можете, как уже писали люди, пометить переменную с помощью volatile или lock it.

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

Взгляните на ManualResetEvent в MSDN .

0
ответ дан 6 December 2019 в 11:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: