Очевидно, что у вас есть 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;
}
Блокировка выполняет две вещи:
Большинство людей понимает первую точку, но не второе. Предположим, что Вы использовали код в вопросе от двух различных потоков с одним потоком, звоня Add
неоднократно и другим потоком, звоня Read
. Атомарность самостоятельно гарантировала бы, что Вы только закончили тем, что читали несколько из 8 - и если бы было два потока, звоня Add
, то Ваша блокировка гарантировала бы, что Вы не "потеряли" дополнений. Однако довольно возможно, что Ваш Read
поток только когда-либо читал бы 0, даже после того, как Add
несколько раз назывался. Без любых барьеров памяти JIT мог просто кэшировать значение в регистре и предположить, что это не изменилось между чтениями. Точка барьера памяти должна или удостовериться, что что-то действительно записано в оперативную память или действительно считано из оперативной памяти.
Модели памяти могут стать довольно волосатыми, но если Вы следуете простому правилу вынимания блокировки каждый раз, когда Вы хотите получить доступ к совместно используемым данным (для чтения или запись), Вы будете хорошо. Посмотрите энергозависимость/атомарность часть моего учебного руководства по поточной обработке для получения дополнительной информации.
Все это зависит от контекста. При контакте с целочисленными типами или ссылками Вы могли бы хотеть использовать членов Система. Поточная обработка. Взаимно блокируемый класс.
А типичное использование как:
if( x == null )
x = new X();
Может быть заменен вызовом к , Взаимно блокировался. CompareExchange () :
Interlocked.CompareExchange( ref x, new X(), null);
Взаимно блокировался. CompareExchange () гарантирует, что сравнение и обмен происходят как атомарная операция.
Другие члены Взаимно блокируемого класса, такой как [1 110] Добавляют () , Декремент () , Exchange () , Инкремент () и Read () , все выполняют их соответствующие операции атомарно. Read документация на MSDN.
Это зависит точно, как Вы собираетесь использовать 32-разрядное число.
, Если Вы хотели выполнить операцию как:
i++;
, Который неявно разламывает на
i
i
, Если другой поток изменяет меня после 1, но прежде 3, затем у Вас есть проблема, где мне было 7 лет, Вы добавляете тот к нему, и теперь это 492.
, Но если Вы просто читаете i или выполняете единственную операцию, как:
i = 8;
затем Вы не должны блокировать i.
Теперь, Ваш вопрос говорит, "... должен заблокировать Int32.NET при чтении его...", но пример включает чтение и затем запись к Int32.
Так, это зависит от того, что Вы делаете.
Наличие только 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 присвоения, чтобы препятствовать тому, чтобы любой другой поток выполнился одновременно.
Блокировка необходима при необходимости в ней, чтобы быть атомарными. Читая и пишущий (как парная операция, такой как тогда, когда Вы делаете меня ++) 32-разрядное число не , гарантировал, что был атомарным из-за кэширования. Кроме того, отдельное чтение или запись не обязательно идут право на регистр (энергозависимость). Создание его энергозависимый не дает Вам гарантии атомарности, если у Вас есть требование изменить целое число (например, чтение, инкремент, операция записи). Для целых чисел взаимное исключение или монитор могут быть слишком тяжелыми (зависит от Вашего варианта использования), и это - то, что Взаимно блокировал, класс для. Это гарантирует атомарность этих типов операции.
в целом блокировки только требуются, когда значение будет изменено
РЕДАКТИРОВАНИЕ: Mark Brackett превосходная сводка более склонна:
"Блокировки требуются, когда Вы хотите, чтобы в других отношениях неатомарная операция была атомарной"
в этом случае, читать 32-разрядное целое число на 32-разрядной машине уже, по-видимому атомарная операция..., но возможно нет! Возможно, энергозависимый ключевое слово может быть необходимым.