Мы должны заблокировать.NET Int32 при чтении его в многопоточном коде?

Очевидно, что у вас есть using namespace std; в области. Следите за тем, чтобы он использовался в файле .h, если вы не можете его найти.

Вы можете устранить двусмысленность, ключевые слова расширения C ++ / CLI, такие как array , находятся в cli Пространство имен. Это компилирует штраф:

#include "stdafx.h"
#include <array>

using namespace std;         // <=== Uh-oh
using namespace System;

int main(cli::array<System::String ^> ^args)
{
    auto arr = gcnew cli::array<String^>(42);
    return 0;
}
14
задан Jader Dias 28 December 2008 в 14:41
поделиться

6 ответов

Блокировка выполняет две вещи:

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

Большинство людей понимает первую точку, но не второе. Предположим, что Вы использовали код в вопросе от двух различных потоков с одним потоком, звоня Add неоднократно и другим потоком, звоня Read. Атомарность самостоятельно гарантировала бы, что Вы только закончили тем, что читали несколько из 8 - и если бы было два потока, звоня Add, то Ваша блокировка гарантировала бы, что Вы не "потеряли" дополнений. Однако довольно возможно, что Ваш Read поток только когда-либо читал бы 0, даже после того, как Add несколько раз назывался. Без любых барьеров памяти JIT мог просто кэшировать значение в регистре и предположить, что это не изменилось между чтениями. Точка барьера памяти должна или удостовериться, что что-то действительно записано в оперативную память или действительно считано из оперативной памяти.

Модели памяти могут стать довольно волосатыми, но если Вы следуете простому правилу вынимания блокировки каждый раз, когда Вы хотите получить доступ к совместно используемым данным (для чтения или запись), Вы будете хорошо. Посмотрите энергозависимость/атомарность часть моего учебного руководства по поточной обработке для получения дополнительной информации.

25
ответ дан 1 December 2019 в 06:59
поделиться

Все это зависит от контекста. При контакте с целочисленными типами или ссылками Вы могли бы хотеть использовать членов Система. Поточная обработка. Взаимно блокируемый класс.

А типичное использование как:

if( x == null )
  x = new X();

Может быть заменен вызовом к , Взаимно блокировался. CompareExchange () :

Interlocked.CompareExchange( ref x, new X(), null);

Взаимно блокировался. CompareExchange () гарантирует, что сравнение и обмен происходят как атомарная операция.

Другие члены Взаимно блокируемого класса, такой как [1 110] Добавляют () , Декремент () , Exchange () , Инкремент () и Read () , все выполняют их соответствующие операции атомарно. Read документация на MSDN.

7
ответ дан 1 December 2019 в 06:59
поделиться

Это зависит точно, как Вы собираетесь использовать 32-разрядное число.

, Если Вы хотели выполнить операцию как:

i++;

, Который неявно разламывает на

  1. чтение значения i
  2. добавление одного
  3. хранение i

, Если другой поток изменяет меня после 1, но прежде 3, затем у Вас есть проблема, где мне было 7 лет, Вы добавляете тот к нему, и теперь это 492.

, Но если Вы просто читаете i или выполняете единственную операцию, как:

i = 8;

затем Вы не должны блокировать i.

Теперь, Ваш вопрос говорит, "... должен заблокировать Int32.NET при чтении его...", но пример включает чтение и затем запись к Int32.

Так, это зависит от того, что Вы делаете.

4
ответ дан 1 December 2019 в 06:59
поделиться

Наличие только 1 блокировки потока ничего не выполняет. Цель блокировки состоит в том, чтобы заблокироваться другой потоки, но она не работает, если никто больше не проверяет блокировку!

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

В Вашем примере, возможно получить сомнительную семантику:

example = 10

Thread A:
   Add(10)
      read example (10)

Thread B:
   Read()
      read example (10)

Thread A:
      write example (10 + 10)

, что означает, ThreadB начал читать значение примера после , поток A начался, это - обновление - но считайте предварительно обновленное значение. Является ли это проблемой или не зависит от того, что этот код, как предполагается, делает, я предполагаю.

, Так как это - пример кода, может быть трудно видеть проблему там. Но, вообразите каноническую встречную функцию:

 class Counter {
    static int nextValue = 0;

    static IEnumerable<int> GetValues(int count) {
       var r = Enumerable.Range(nextValue, count);
       nextValue += count;
       return r;
    }
 }

Затем следующий сценарий:

 nextValue = 9;

 Thread A:
     GetValues(10)
     r = Enumerable.Range(9, 10)

 Thread B:
     GetValues(5)
     r = Enumerable.Range(9, 5)
     nextValue += 5 (now equals 14)

 Thread A:
     nextValue += 10 (now equals 24)

nextValue увеличен правильно, но возвращенные диапазоны наложатся. Значения 19 - 24 никогда не возвращались. Вы зафиксировали бы это путем блокировки вокруг var r и nextValue присвоения, чтобы препятствовать тому, чтобы любой другой поток выполнился одновременно.

2
ответ дан 1 December 2019 в 06:59
поделиться

Блокировка необходима при необходимости в ней, чтобы быть атомарными. Читая и пишущий (как парная операция, такой как тогда, когда Вы делаете меня ++) 32-разрядное число не , гарантировал, что был атомарным из-за кэширования. Кроме того, отдельное чтение или запись не обязательно идут право на регистр (энергозависимость). Создание его энергозависимый не дает Вам гарантии атомарности, если у Вас есть требование изменить целое число (например, чтение, инкремент, операция записи). Для целых чисел взаимное исключение или монитор могут быть слишком тяжелыми (зависит от Вашего варианта использования), и это - то, что Взаимно блокировал, класс для. Это гарантирует атомарность этих типов операции.

2
ответ дан 1 December 2019 в 06:59
поделиться

в целом блокировки только требуются, когда значение будет изменено

РЕДАКТИРОВАНИЕ: Mark Brackett превосходная сводка более склонна:

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

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

0
ответ дан 1 December 2019 в 06:59
поделиться
Другие вопросы по тегам:

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