Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Странный deadlock [D7, WinXP]


Страницы:   1 2

mt2 ©   (2008-01-14 15:37:00) 

Hi,

unit Unit1;
// Delphi-7
// Странный deadlock, см. строки:
// Почему эта программа зависает без sleep(0) ?
// Если n=200, то  эта программа работает без sleep(0). Почему?

// Испытано под MS Windows XP SP2, CPU Intel Pentium-4 3.0 GHz
// и на другом CPU Intel Pentium-4 3.2 GHz

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type

 TForm1 = class(TForm)
   Button1: TButton;
   Memo1: TMemo;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

 TTestThread = class(TThread)
   constructor Create (CreateSuspended : Boolean; eventHnd : THandle; i : integer);
 private
   { Private declarations }
   ind : integer;
   syncEvent : THandle;
 protected
   procedure Execute; override;
 end;

var
 Form1: TForm1;
 events  : array [0..7] of THandle;
 thr : array [0..7] of TTestThread;
 stop : Boolean;
 n : integer;
 calc : array [1..8] of integer;

implementation

{$R *.dfm}

constructor TTestThread.Create (CreateSuspended : Boolean; eventHnd : THandle; i : integer);
begin
inherited Create (CreateSuspended);
syncEvent := eventHnd;
ind := i;
end;

procedure TTestThread.Execute;
begin
 { Place thread code here }
 repeat
   inc(calc [ind],n);
   SetEvent (syncEvent);
   suspend;
 until stop;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 i : integer;

begin
for i:=1 to 8 do
 calc [i] := i;

stop := false;

for i:=0 to 7 do
 events [i] := CreateEvent (nil, true, false, PChar('testEvent'+intToStr(i)));

for i:=0 to 7 do
 thr[i] := TTestThread.Create(true, events [i],i+1);

n := 0;
repeat
 inc (n);

 thr[0].Resume;
 thr[1].Resume;
 thr[2].Resume;
 thr[3].Resume;
 thr[4].Resume;
 thr[5].Resume;
 thr[6].Resume;
 thr[7].Resume;

 waitForMultipleObjects (8, @events, true, INFINITE);
 ResetEvent (events [0]);
 ResetEvent (events [1]);
 ResetEvent (events [2]);
 ResetEvent (events [3]);
 ResetEvent (events [4]);
 ResetEvent (events [5]);
 ResetEvent (events [6]);
 ResetEvent (events [7]);

 sleep(0); // Почему эта программа зависает без sleep(0) ?

until n=1000; // Если n=200, то  эта программа работает без sleep(0). Почему?

Memo1.Lines.Add('n= '+ intToStr(n));
for i:=1 to 8 do
 Memo1.Lines.Add(intToStr(calc[i]));
end;

end.


ага   (2008-01-14 19:49:00) [21]

На многопроцессорной тачке это могло долго не проявиться. А могло и сразу. В общем, все единл фтопку.


ага   (2008-01-14 19:46:00) [22]


> Такой момент, когда все потоки одного успели вызвать

Такой момент, когда все потоки кромеодного успели вызвать


ага   (2008-01-14 19:45:00) [23]

А, ну да, еще ж про Sleep. Sleep усыпляет на квант планировщика главный поток, в результате наш несчастный "последний" поток получает возможность вызвать свой Suspend раньше, чем главный поток вызовет ему Resume.


> Сергей М. ©   (14.01.08 17:11) [6]

Ну че абракадабра-то? Нормально сделал, выдернул проблему, лишнего не постил.


ага   (2008-01-14 19:40:00) [24]


> Если n=200, то  эта программа работает без sleep(0)

Эт тока кажется. А виснет вот почему.

Такой момент, когда все потоки одного успели вызвать SetEvent и уйти в Suspend.  В какой-то момент последний поток успевает вызвать SetEvent и  в этот момент планировщик у него отбирает процессор и отдает гланому - главный-то поток интерфейсный, у его окна фокус, потому у него приоритет повыше.

Главный поток сбрасывает все эвенты и резюмит все потоки. Все кроме последнего - он-то еще не успел уснуть и Resume ему по барабану. Далее главный поток уходит в WaitFor... и процессор достаетс последнему из потоков. Тот просыпается и вызывает свой Suspend.

Все, аллес. Спит главный поток, потому что у нег WaitAll = true, спит наш несчастный последний поток в своем Suspend. Отработают свои циклы и уснут все остальные потоки. Все спят, и разбудить их некому. Кроме TerminateProcess.

Б-р-р-р...


Сергей М.   (2008-01-14 17:11:00) [25]


> отловил bug и минимизировал


И ?


> Лишние детали будут не по теме


Продолжай париться.


> Попробуй для начала запустить


Да нахрен оно мне надо


> что получается, и почему.


Получится хня.

Почему ?

потому что абракадабра в коде.


icWasya   (2008-01-14 17:09:00) [26]

после waitForMultipleObjects (8, @events, true, INFINITE);
ResetEvent не нужно


mt2   (2008-01-14 16:36:00) [27]

ТЗ  будет слишком долго, прога сложная, отловил bug и минимизировал. Лишние детали будут не по теме. Попробуй для начала запустить у себя и сообщи, что получается, и почему.


Сергей М.   (2008-01-14 16:13:00) [28]

Что это вообще за хня ?

Изложи ТЗ.


mt2   (2008-01-14 15:48:00) [29]

:) может они (странности) не только мои? но и ОС? - тогда и тебя поздравляю ;))))))))))


Сергей М.   (2008-01-14 15:44:00) [30]

Поздравляем тебя с имеющими тебя странностями.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо