Форум: "Потрепаться";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];
ВнизОпять о синхронизации в потоках. Найти похожие ветки
← →
Alexander Panov © (2005-06-04 21:38) [0]Исходный и скомпилированный код:
i:=0;
xor eax,eax
mov [i],eax
b:=True;
mov byte ptr [b],$01
i1:=1;
mov [i1],$00000001
b1:=False;
mov byte ptr [b1],$00
i1 := i;
mov eax,[i]
mov [i1],eax
b1 := b;
mov al,[$0045ccac]
mov [$0045ccad],al
Вопрос:
Потокобезопасно ли выполнение каждой инструкции исходного кода в приведенном выше примере?
← →
SPeller © (2005-06-04 21:50) [1]Потокобезопасна только одна машинная инструкция. Инструкция языка, состоящая из нескольких машинных команд - НЕ потоко-безопасна.
← →
Alexander Panov © (2005-06-04 22:07) [2]SPeller © (04.06.05 21:50) [1]
Потокобезопасна только одна машинная инструкция. Инструкция языка, состоящая из нескольких машинных команд - НЕ потоко-безопасна.
Таким образом, защищать Integer- и Boolean- переменные тоже необходимо при многопоточной работе?;)
← →
Alexander Panov © (2005-06-04 22:08) [3]Забыл добавить, как орпределены переменные:
var
i, i1: Integer;
b, b1: Boolean;
Все переменные глобальные.
← →
Kerk © (2005-06-04 23:23) [4]Alexander Panov © (04.06.05 22:07) [2]
Таким образом, защищать Integer- и Boolean- переменные тоже необходимо при многопоточной работе?;)
Защищать необходимо любые данные объявленные используемые глобально. Независимо от типа.
← →
Alexander Panov © (2005-06-04 23:41) [5]Kerk © (04.06.05 23:23) [4]
Защищать необходимо любые данные объявленные используемые глобально. Независимо от типа.
Я-то согласен, но помнится, что кто-то утверждал, что такие операции являются атомарными.
← →
Dezmond (2005-06-05 00:01) [6]Alexander Panov © (04.06.05 21:38)
Работа с однобайтовыми переменными потокаезопасна, их синхронизируют аппаратные арбитры, по крайней мере мне так Digitman говорил...
← →
Eraser © (2005-06-05 00:08) [7]Dezmond = Eraser
Вот думаю, ник менять или нет...
← →
Alexander Panov © (2005-06-05 00:19) [8]Dezmond (05.06.05 0:01) [6]
Работа с однобайтовыми переменными потокаезопасна
Однако пример кода показывает другое.
b1 := b;
mov al,[$0045ccac]
В этот момент система может переключиться на выполнение другого потока и он может изменить значение по адресу $0045ccac
mov [$0045ccad],al //Здесь получим неверное значение.
← →
Eraser © (2005-06-05 00:22) [9]Alexander Panov © (05.06.05 00:19) [8]
Я точно не знаю "механики" работы процессора, но думаю ЧеловекЦифра не зря так написал, я ещё переспросил тогда...
Возможно эта проблема решается на аппаратном уровне, хотя ума не приложу как.
← →
-=XP=- © (2005-06-05 03:02) [10]При переключении между потоками, процессор сохраняет состояние регистров для каждого потока. Таким образом, при возвращении к потоку, его работа будет продолжена.
И в примере:mov eax,[i]
mov [i1],eax
нет ничего потокоопасного. Не важно, на какой инструкции поток заснет, ожидая выполнения других потоков. Важно другое, то, что переменная i1 примет значение, равное i. Порчи данных при этом не будет. Именно это важно.
Для примера, сравните:type
TMyRec = record
i1: integer;
i2: integer;
end;
var
MR1, MR2: TMyRec;
begin
MR1.i1 := 100; // 1
MR1.i2 := 100; // 2
MR2 := MR1; // 3
end;
Операции 1, 2 являются атомарными. Не важно, когда поток будет временно приторможен процессором. Важно то, что по очереди в MR1.i1 окажется значение 100, в MR.i2 окажется значение 100. И речь в данном случае именно о числе 100. Именно об этом идет речь. В ходе операций 1 и 2 в поля i1 и i2 будут записано 100. Ни 20, ни 50, ни 98. Только 100. В этом и заключается атомарность операции. Процессор никогда не запишет в поле i1 или i2 часть битов числа 100, а затем переключится на выполнение другого потока. Или все число 100, или ничего. Вот в этом атомарность.
А вот операция 3 не является атомарной. И может сложится ситуация, когда переключение между потоками будет произведено в момент выполнения операции 3. И в переменной MR2 будет не (i1: 100; i2: 100), а (i1: 100; i2: 0) или (i1: 100; i2: -57), что, впрочем, зависит от начального значения MR2. Логично, что в этот момент другой поток, полагающийся на значение MR2, будет заниматься ерундой, производя какие-то там вычисления с этой переменной.
То же относится и к совокупности операций 1 и 2 - вместе они потоконебезопасны, так как поток может притормозить между ними.
Но, опять же таки, смотря как взглянуть - мало ли для чего используются данные записей MR1 и MR2. На самом деле в данной ситуации все очень сильно зависит от контекста.
Говоря в общих чертах - код, изменяющий несколько логически взаимно связанных переменных, или даже одну переменную, операции с которой являются неатомарными, - потоконебезопасный.
Вот строки символов (особенно динамические строки Delphi) - практически без контекста - потоконебезопасны. Если один поток начнет переписывать значение длины строки (то, которое по 0-му смещению), собираясь потом выделить под новую строку память, и, сразу же после этого, другой поток обратится к этой строке - то суждено ему работать с неправильно распределенной памятью, опираясь на новое значение длины строки. Я уже не говорю про подсчет количества ссылок.
А представьте, что произойдет, если во время выполнения MyPersistent1.Assign(MyPersistent2) произойдет переключение между потоками? Это ж никто не знает (кроме автора класса), что в методе AssignTo происходит, какие данные копируются, и когда ядро ОС решит переключить этот поток на какой-то другой (а этого уже точно никто не знает).
Так что приведенные в вопросе примеры - потокобезопасны, если между собой никак логически не связаны.
← →
Суслик © (2005-06-05 10:26) [11]
> Alexander Panov © (04.06.05 21:38)
Саш, ты того, почитал бы что-нить по теме потоков (плюс к тому, что уже прочел). Например, Рихтер "win для профессионалов" четвертое издание, стр. 140-141.
← →
Igorek © (2005-06-05 12:13) [12]А что такое потокобезопасность?
← →
Eraser © (2005-06-05 13:30) [13]А что такое потокобезопасность?
Это гарантия того, что в определённый момент N данные Z доступны только ОДНОМУ потоку.
← →
Alexander Panov © (2005-06-05 14:00) [14]Суслик © (05.06.05 10:26) [11]
Вот-вот.
Снова читал Рихтера, потому и возник такой вопрос.
-=XP=- © (05.06.05 3:02) [10]
Измени на
MR1.i1 := 100; // 1 на MR1.i1 := 0;
Операция сразу перестанет быть атомарной.
В момент присвоения поток может быть прерван. Если во втором потоке выполняется операция сравнения, которая завист от MR1.i1, то результат сравнения будет не тот, который ожидается.
← →
Igorek © (2005-06-05 23:07) [15]Eraser © (05.06.05 13:30) [13]
Это гарантия того, что в определённый момент N данные Z доступны только ОДНОМУ потоку.
Тогда не существует непотокобезопасного кода на 1 проц. платформах.
Страницы: 1 вся ветка
Форум: "Потрепаться";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.039 c