Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.04.11;
Скачать: CL | DM;

Вниз

TTread + Terminate.   Найти похожие ветки 

 
Тимохов ©   (2004-04-16 15:05) [0]

Продолжаю изучать потоки и все с этим связанное.

Есть метод TThread.Terminate. Зачем этот метод и как им пользоваться я знаю.
Вопрос по телу этого метода.
У меня в Д6 оно состоит из одной строки FTerminated := True;
Метод Terminate обычно вызывается из одного потока, а обращение к свойству Terminated из другого.
Как видно здесь никаких методов синхронизации не предусмотрено (я не нашел).
Вопрос: почему не возникает проблем многопоточного доступа в переменной?


 
Reindeer Moss Eater ©   (2004-04-16 15:07) [1]

Нет никакой переменной


 
Тимохов ©   (2004-04-16 15:10) [2]


> Reindeer Moss Eater ©   (16.04.04 15:07) [1]

А FTerminated?
Ну хорошо - атрибутов, так лучше?
Т.е. не понял ответа


 
Reindeer Moss Eater ©   (2004-04-16 15:12) [3]

А почему должны быть проблемы многопоточного доступа?
Это что, ресурсы GDI задевает или еще что?


 
Семен Сорокин ©   (2004-04-16 15:13) [4]

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


 
Reindeer Moss Eater ©   (2004-04-16 15:18) [5]

Он (автор) имел ввиду

procedure TThread.Terminate;
begin
 FTerminated := True;
end;

И все же, откуда мнение, что проблемы должны быть?


 
Тимохов ©   (2004-04-16 15:18) [6]


> имхо, этот атрибут из основного потока - только для чтения,
> ты же

Вызов termiante идет из основного потока, поэтому и изменение идет в коде основного потока.


> Reindeer Moss Eater ©   (16.04.04 15:12) [3]

Но вот арифметическая операция над атрибутом из разных потоков точно требует синхронизации. Т.е. почему для операции присваивания синхронизации не требуется.


 
Reindeer Moss Eater ©   (2004-04-16 15:20) [7]

Но вот арифметическая операция над атрибутом из разных потоков точно требует синхронизации.

Атрибутом КАКИХ классов? Всех? Черта с два.


 
Тимохов ©   (2004-04-16 15:31) [8]


> Reindeer Moss Eater ©   (16.04.04 15:20) [7]

Поясняю вопрос.
var
  // глобальная, доступна из основоного потока и доп потока.
  i: int64;

begin
  // в основном потоке ...
  i := 23424323431243142;
end;

присвоение равносильно
mov [ebp-$10],$4d391d86
mov [ebp-$0c],$0053384c

т.е. команды 2, а не одна.

В данном случае основной поток может прерваться и доп поток будет работать не с нужным значением, а только с чатью $4d391d86.

Вы хотите сказать, что и в этом случае не нужна синхронизация?


 
Семен Сорокин ©   (2004-04-16 15:31) [9]

Тимохов ©   (16.04.04 15:18) [6]
Вызов termiante идет из основного потока, поэтому и изменение идет в коде основного потока.

вот-вот, немного не так выразился, так изменения в самом потоке св-ва Terminate нет!
там только проверка по этому аотрибуту, поэтому проблем совместного доступа не должно быть.


 
Тимохов ©   (2004-04-16 15:32) [10]


> Семен Сорокин ©   (16.04.04 15:31) [9]

посмотрите 8.
что вы на это скажете?


 
Verg ©   (2004-04-16 15:34) [11]


>  Т.е. почему для операции присваивания синхронизации не
> требуется.


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


 
Reindeer Moss Eater ©   (2004-04-16 15:34) [12]

Тимохов ©

И как эта хрень с твоим вопросом связана?

не говоря уже о том, что FTerminated: Boolean; а не int64


 
KSergey ©   (2004-04-16 15:35) [13]

> Reindeer Moss Eater ©   (16.04.04 15:07)
> Нет никакой переменной

А для тупых подробнее можно? ;)

> [3] Reindeer Moss Eater ©   (16.04.04 15:12)
> А почему должны быть проблемы многопоточного доступа?
> Это что, ресурсы GDI задевает или еще что?

Это что-то еще. Разве нет? ;)
Да и разве просбемы многопоточности - проблемы лишь в GDI?

> Семен Сорокин ©   (16.04.04 15:13)
> Вопрос: почему не возникает проблем многопоточного доступа
> в переменной?
> имхо, этот атрибут из основного потока - только для чтения,
> ты же не можешь задать Terminated := ... поэтому нет средств
> для синзронизации.

Да, но его код выполняется в рамках основного потока... Т.е. фактически в основном потоке выпоняется это присваивание.

Рискну высказать свой вариант:
В любом случае минимальной единицей выполяемого кода является одна инструкция процессора.
Переменная типа Boolean - это 1 байт. Т.е. ее заполнение/чтение  - это одна команда процессора. Рассмотрим такой сценарий событий: в основном потоке подошли непосредственно к машинной команде записи в эту переменную (ее ячейку памяти) значения 1. В доп потоке подошли к выполнению команды чтения из этой ячейки (метод Get св-ства Terminated). Даже если перед самой записью в основном потоке произойдет переключение на дополнительный - ничего срашного: прочитается значение на данный момент. Если перед самым чтением в доп. потоке произойдет переключение в основной - сколько угодно: пропишется новое значение (в основном) и позже в доп. прочитается новое.

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

Если все вру - прошу прощения.
Надеюсь - поправят.


 
Тимохов ©   (2004-04-16 15:35) [14]


> При том переменная в один байт и присваивание ей или проверка
> ее на что-то происходит в одну машинную команду

Похоже, что вот именно это и является здесь главным.

В присвоении fterminated есть однозначное предположение, что выполнение произойдет в одну команду.


 
Семен Сорокин ©   (2004-04-16 15:36) [15]

Тимохов ©   (16.04.04 15:32) [10]
а если так:

var
 // глобальная, доступна из основоного потока и доп потока.
 i: boolean;


 
Verg ©   (2004-04-16 15:38) [16]

Для сравнения: код, который якобы изображает из себя критическую секцию.

while flag do; //
flag := true;  // Вход в "критическую секцию"
// Здесь казалось бы одновременно может "находится" только один поток, который первый обнаружит not flag
flag := false; // Типа выход из "КС"


 
Тимохов ©   (2004-04-16 15:38) [17]


> Семен Сорокин ©   (16.04.04 15:36) [15]

Тогда будет все ок.

Вопрос почти снят: спасибо verg и KSergey - они подствердили мои предположения.

Но хотелось бы еще кого-нибудь и св. синих услышать...


 
KSergey ©   (2004-04-16 15:42) [18]

Прошу прощения, [13] KSergey ©   (16.04.04 15:35) писалось когда еще не было
[11] Verg ©   (16.04.04 15:34)
[12] Reindeer Moss Eater ©   (16.04.04 15:34)
[14] Тимохов ©   (16.04.04 15:35)

> [12] Reindeer Moss Eater ©   (16.04.04 15:34)
> И как эта хрень с твоим вопросом связана?
> не говоря уже о том, что FTerminated: Boolean; а не int64

Не, ну человек хочет "разобраться что к чему. Законно." (с) ;)
В подробностях.
Так что прошу не уклоняться и ответить на > [8] Тимохов по-нашему, по-программистски: да или нет. ;) (может/не может быть проблем)


 
Reindeer Moss Eater ©   (2004-04-16 15:42) [19]

procedure TThread.Terminate;
begin
FTerminated := True;
end;

Это, как и любой другой метод кроме Execute выполняется в контексте того потока, который вызвал метод, а не в контексте Execute


 
Verg ©   (2004-04-16 15:43) [20]


> Тимохов ©   (16.04.04 15:35) [14]
>
> > При том переменная в один байт и присваивание ей или проверка
>
> > ее на что-то происходит в одну машинную команду
>
> Похоже, что вот именно это и является здесь главным.


В данном, конктретном случае даже если бы эта переменная была бы Int64, то перевод любой составляющей длинного слова в положение ненуль (хоть одной тетрады, хоть одного бита, хоть какой части) будет давать true на проверку
if Var64 <> 0 then
 exit;
И поток завершиться, выйдет из цикла или еще чего там надо... И все, цель достигнута.


 
Тимохов ©   (2004-04-16 15:44) [21]


> KSergey ©   (16.04.04 15:42) [18]

В 8 я не спрашивал будут или нет проблемы. Я и сам знаю - будут.


> Reindeer Moss Eater ©   (16.04.04 15:42) [19]

Это вообще кому?


 
Тимохов ©   (2004-04-16 15:45) [22]


> Verg ©   (16.04.04 15:43) [20]

В данном конкретном случае действительно понятно. Но ведь хочется методику понять: когда нужно делать синхронизацию, когда нет. Вот строки вы же так не рискнюте присваивать? :))))


 
Reindeer Moss Eater ©   (2004-04-16 15:45) [23]

Это на пост который остался высоко вверху.
Не вам


 
Romkin ©   (2004-04-16 15:50) [24]

Да какя разница, во сколько команд происходит присвоение? Чужой поток может только присвоить, а собственный - читает значение через terminated. Как бы часто он не читал, переменная изначально выставлена в false, и не важно, будет ли поток ее читать, в то время как доругой ее меняет, или нет. Как поменяет - будет прочитано true.
Вот и все, только два значения, причем чужой поток может выставить только одно из них. Поэтому синхронизация не требуется.


 
Тимохов ©   (2004-04-16 15:52) [25]


> Romkin ©   (16.04.04 15:50) [24]

С переменной типа booloean вроде разобрались.

А для int64. Что тоже считаете разницы нет?


 
Digitman ©   (2004-04-16 15:57) [26]


> Тимохов ©   (16.04.04 15:05)  


флейм по сабжу не стоит и выеденного яйца

boolean - это байт

инструкция модификации байта не м.б. прервана в связи с мультизадачностью

поток получил квант времени и модифицировал байт памяти ... все ! никто и ничто не прервет инструкцию MOV BYTE PTR...  !!

а далее квант получил иной поток, заинтересованный в чтении байта .. он делает чтение/тест этого байта - и эта инструкция тоже не прерывается !


 
Тимохов ©   (2004-04-16 15:58) [27]

Сим ответом и удовлетворю свой интерес.
Всем спасибо.


 
KSergey ©   (2004-04-16 15:59) [28]

> [26] Digitman ©   (16.04.04 15:57)
> флейм по сабжу не стоит и выеденного яйца

И не надо разводить!
неужели жалко сказать: вот тут будет, тут нет. И все. ;)


 
Digitman ©   (2004-04-16 15:59) [29]


> А для int64. Что тоже считаете разницы нет?


есть. и  - ощутимая !

ощутимая до поры, пока исполняется 32-разрядная ОС на машине с 64-разрядным ЦП


 
Тимохов ©   (2004-04-16 16:02) [30]


> Digitman ©   (16.04.04 15:59) [29]

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

Почему у нас нет конкурса на самого полезного игрока? :)))


 
Digitman ©   (2004-04-16 16:04) [31]


> на самого полезного игрока


смотря во что и на что играть) ...

шары катать ? на "шары" о ставках базар вести ?)

кажись, это и так здесь в избытке)))


 
Romkin ©   (2004-04-16 16:12) [32]

Тимохов ©  (16.04.04 15:52) [25] Байты, биты... Если бы было объявлено как longBOOL - тоже нет разницы.
Ведь состояние может измениться только на одно другое, и возвращаться обратно не будет. Хоть сколько раз установи в true, придет время - прочитают.
То есть, это очень узкая вещь... Но здравый смысл поможет :))
Есть переменная, никто по-умолчанию не запрещает одновременно читать/писать ее любому числу потоков. ТАк?
Можно запретить писать, можно запретить читать. Вопрос - когда.
Очень просто: Если при чтении во время записи возможно чтение не того, что надо - надо синхронизировать. Это - при сложных объектах. Если у тебя простая переменная, в которую один поток только пишет (строка - составная!), то понятно, что другие потоки пусть ее читают сколько влезет. Касательно int64  - я бы не рисковал, на старых процессорах вполне возможна запись ее за два такта, и чтение в промежутке между ними. Если допустимо - ок...


 
Verg ©   (2004-04-16 17:05) [33]


> Romkin ©   (16.04.04 16:12) [32]



> возможна запись ее за два такта,


Такт или два на однопрцессорной машине - значение не имеет, т.к. аппаратные прерывания (за чсет которых, по-сути и происходит передача управление thread менеджеру) возможны только между командами (исключение - цепочечные операции).
А вот в многопроцессорной машине - там да, там всякое может быть.
Вот для этого и существют в API специальные ф-ции из серии
InterLocked..... Xсhange, Increment, Decrement и т.п.


 
Игорь Шевченко ©   (2004-04-16 23:57) [34]


> А вот в многопроцессорной машине - там да, там всякое может
> быть.


Конечно. Один процесс начал в память байт записывать, записал четыре бита, а в это время другой процессор начал читать и прочитал такую ерунду...


 
KSergey ©   (2004-04-17 07:10) [35]

> [34] Игорь Шевченко ©   (16.04.04 23:57)
> Конечно. Один процесс начал в память байт записывать, записал
> четыре бита, а в это время другой процессор начал читать
> и прочитал такую ерунду...

Мммм... Это шутка, я надеюсь??


 
Verg ©   (2004-04-17 13:07) [36]


> KSergey ©   (17.04.04 07:10) [35]


Я тоже не понял....


 
nikkie ©   (2004-04-17 14:54) [37]

а можно я тоже задам вопрос про TThread? про Synchronize?

вам не кажется, что то, что Synchronize является методом TThread - это неудобно? ситуация такая: создается потомок TThread, который выполняет какую-то работу. достаточно сложную и разноплановую. для чего вызывает уже не свои методы а методы каких-то других объектов. а те - еще чьи-нибудь методы. и вот где-то на нижнем уровне требуется реализовать нечто - логирование, подсчет траффика или еще что, что требует синхронизации. откуда взять TThread? передавать во все используемые объекты? не слишком ли жирно?

как бы вы выкручивались бы в этой ситуации? я склоняюсь к тому, чтобы синхронизацию сделать просто посылкой сообщения главному окну. собственно почти так и сделано в D5 (в D6 просто страх какой-то творится - видимо это для единообразия с Kylix-ом), только сообщение посылается некоему ThreadWindow. кстати, при такой реализации и не понятно, зачем было бы не сделать Synchronize классовым методом или обычной процедурой. другое кстати - Synchronize в D5, как я понимаю, исполняет метод в контексте не основного потока, а в контексте первого потока, создавшего объект типа TThread (а, например, такая ситуация - потоки уже есть, хотя TThread еще никто не создавал - легко может возникнуть в DLL).


 
Игорь Шевченко ©   (2004-04-17 21:21) [38]

KSergey ©   (17.04.04 07:10)
Verg ©   (17.04.04 13:07)

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


 
Тимохов ©   (2004-04-18 10:58) [39]


> Игорь Шевченко ©   (17.04.04 21:21) [38]

Не томите, скажите сами ? :)))))))))


 
Digitman ©   (2004-04-18 11:26) [40]


> Игорь Шевченко


а про кэш-арбитр ты почему-то умолчал)



Страницы: 1 2 вся ветка

Текущий архив: 2004.04.11;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.029 c
4-1079858504
tytus
2004-03-21 11:41
2004.04.11
Как перехватить сообщения WM_VSCROLL и WM_HSCROLL?


1-1080159419
Eine Komsomolka
2004-03-24 23:16
2004.04.11
Компонент для хранения на себе компонентов


14-1079462747
Soft
2004-03-16 21:45
2004.04.11
Манеж сгорел, клоун остался...


1-1079721543
ser_ega
2004-03-19 21:39
2004.04.11
Округление числа!!!


4-1079308855
kothor
2004-03-15 03:00
2004.04.11
Есть вопрос по меню.