Подтвердить что ты не робот

Является ли чтение двойным, не потокобезопасным?

Обновление: я просто наткнулся на это в ответе Эрика Липперта на другой вопрос (он цитирует спецификацию):

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

ОК, поэтому чтение double не является атомарным. Это означает, что значение может быть изменено в середине чтения, правильно? Итак, как вы читаете значение double атомарно?


Я заметил там Interlocked.Read метод для значений long. Это имеет смысл для меня, так как чтение 64-битного значения должно требовать двух шагов и, следовательно, подвергать условиям гонки, как и любое другое неатомное действие.

Но нет значений Interlocked.Read для double, хотя System.Double - это 64-разрядное значение.

Я вижу странное поведение в моей программе, где мой графический интерфейс, который отображает double в текстовом поле, в то время как double также часто обновляется другими потоками, показывает правильное значение (в окрестности 200.0) в большинстве случаев, а затем случайным образом отображая ошибочное значение (например, -0.08).

Возможно, это проблема с потоками, или, может быть, это что-то еще. Но сначала я хотел сузить возможности. Итак: читает double потокобезопасный?

4b9b3361

Ответ 1

Обычный способ: управлять доступом с помощью блокировки.

Ответ 2

читает двойной потокобезопасный?

Нет. Как говорится в спецификации

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

Перемещение.

Это означает, что значение может быть изменено в середине чтения, правильно?

Да.

Итак, как можно считать двойное значение атомарно?

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

И вопрос, о котором вы не спрашивали, но часто спрашивается в качестве ответа на ваши вопросы:

Делает ли поле "изменчивым" чтение/запись его атомарным?

Нет. Нелегко сделать volatile поле типа double.

Ответ 3

Используйте Interlocked.Exchange ИЛИ Interlocked.CompareExchange для атомарного чтения следующим образом.

Interlocked.Exchange(ref somevariable, somevariable)

Возвращает исходное значение.

Если вы хотите избежать использования текста compareExchange.

Interlocked.CompareExchange(ref somevariable, somevalue, somevalue);

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

Ответ 4

Только для CLR promises выравнивание переменной 4. Это означает, что вполне возможно, что длинная или двойная граница будет перекрывать границы линии кэша ЦП. Это гарантирует, что чтение будет неатомным.

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