Простые типы являются «поточно-ориентированными», если они могут быть прочитаны за один раз (или записаны за одну запись) из памяти.Я не уверен, определяется ли он шириной шины памяти процессора или их «целочисленным» размером (32 бита против 64-битного процессора).Может быть, кто-то еще может уточнить эту часть.
Я знаю, что размер чтения в настоящее время составляет не менее 32 бит.(Раньше в Intel 286 дней это было только 8 битов за раз).
Хотя об этом нужно знать одну вещь.Даже если он может читать 32 бита за раз, он не может начать чтение только с любого адреса.Это должно быть кратно 32 битам (или 4 байта).Таким образом, даже целое число может быть прочитано в 2 последующих чтениях, если оно не выровнено по 32 битам.К счастью, компилятор автоматически выровняет почти все поля по 32 битам (или даже 64 битам).
Хотя есть исключение, упакованные записи никогда не выравниваются, и, таким образом, даже целое число в такомзапись не будет поточно-ориентированной.
Из-за своего размера int64 также не является поточно-ориентированной.То же самое можно сказать о большинстве плавающих типов.(За исключением Single, я верю).
Теперь, учитывая все это, есть некоторая ситуация, когда вы могли бы написать глобальную переменную из нескольких потоков и при этом быть «потоко-безопасными».
Например,
var
LastGoodValueTested : Integer
procedure TestValue(aiValue : Integer);
begin
if ValueGood(aiValue) then
LastGoodValue := aiValue
end;
здесь вы можете вызвать подпрограмму TestValue из нескольких потоков, и вы не станете повреждать переменные LastGoodValueTested.Может случиться так, что значение, записанное в переменную, не будет самым последним.(Если происходит переключение контекста потока между ValueGood (aiValue) и назначением).Таким образом, в зависимости от потребностей, это может / не может быть приемлемо.
Теперь,
var
gLogCounter: Integer = 0;
procedure Log(S : string);
begin
gLogCounter := gLogCounter + 1;
end;
Здесь вы можете повредить счетчик, потому что это неодинарная операция.Сначала вы читаете переменную.Затем добавьте 1 к нему.Тогда вы сохраните его обратно.Переключение контекста потока может произойти в середине этой операции.Так что это случай, который требует синхронизации.
В этом случае его можно переписать в
procedure Log(S : string);
begin
InterlockedIncrement(gLogCounter);
end;
Я бы подумал, что это немного быстрее, чем при использовании критических разделов ... Но яЯ не уверен.