Тема безопасности чтения Guid Дважды - PullRequest
0 голосов
/ 12 февраля 2019

Я читаю объект Guid дважды, один раз в операторе if и один раз в блоке оператора if.

В CI локально скопировал бы переменную, чтобы убедиться, что операция чтениявнутри оператора if не читается другое значение (если другой поток изменяет это значение между ними). ​​

Я скептически отношусь к тому, что следующий подход является а) потокобезопасным и б) даст мне то же значение:

public class MyClass {

private Guid MyProp {get;set;} = Guid.Empty; //May be changed at will

public OnRunLoop() //Gets called periodicaly on a thread
{

    var ALocalCopyOfTheProp = MyProp; //Copy locally
    if(ALocalCopyOfTheProp == AValueFromAnotherPlace) //Read 1
    {
        ...

        var AnotherReadOfTheVariable = ALocalCopyOfTheProp; //Read 2

    }

    ...
}

C # .NET изначально не имеет возможности копирования из моего поиска в Google, так что лучше в таком случае, как этот?

Редактировать: - Обратите внимание, что в этом случае MyProp отключениз моих рук.Я не могу использовать замок, так как собственность исходит из другого места.(извиняюсь за то, что не сделал это более понятным) - Guid - это структура, а не ссылочный тип

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

В CI будет копировать переменную локально, чтобы убедиться, что операция чтения внутри оператора if не читает другое значение (если другой поток изменяет это значение между).

Я отмечаю, что этот метод просто заменяет одну проблему - непоследовательные чтения - на другую проблему - устаревшие чтения.

Этот метод распространен в C # в многопоточных обработчиках событий;Вы часто видите что-то вроде:

var myEvent = this.MyEvent;
if (myEvent != null) myEvent(whatever);

Хотя это и решает проблему состояния гонки, когда this.MyEvent изменяется между if и вызовом, это не решает более глубокой проблемы: вы можете сделатьпроверка в одном потоке, установите для обработчика событий значение null в другом потоке, и теперь предположение о том, что обработчик событий больше никогда не будет вызываться, равно false , потому что устаревшее значение будет вызываться в другомнить!

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

Объект Guid является ссылочным типом

Это абсолютно не так.

C # .NET изначально не имеет возможностей копирования из моего поиска в Google, так что лучше всего использовать втакой случай?

Снять замок.

Я не могу использовать замок

Тогда вам нужно только позвонитьВаша собственность в одной теме.

0 голосов
/ 12 февраля 2019

Guid является структурой (тип значения), и его размер больше, чем атомарно считанные значения, которые составляют 32 или 64 бита в зависимости от ОС ( Какие операции являются атомарными в C #? ).

В результате вы не можете прочитать (или записать) Guid значение в поточно-ориентированном режиме, если значение можно изменить из других потоков.Доступ к коду Guid (как чтение, так и запись) должен быть защищен некоторым механизмом синхронизации (например, lock).

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

...