若不是因为你

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

看《Delphi 7 高级应用开发教程》的朋友,你们好。(没在看也没关系,呵呵)

第一章讲多线程技术及其应用,里面讲到互斥对象,书中给出的实现代码如下

  1 unit Unit1;
  2 
  3 interface
  4 
  5 uses
  6   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7   Dialogs, StdCtrls;
  8 
  9 const
 10   MaxSize = 20;
 11 
 12 type
 13   TThreadTest = class(TThread)
 14   protected
 15     procedure Execute; override;
 16   end;
 17 
 18   TForm1 = class(TForm)
 19     Memo1: TMemo;
 20     Memo2: TMemo;
 21     Button1: TButton;
 22     procedure FormCreate(Sender: TObject);
 23     procedure FormDestroy(Sender: TObject);
 24     procedure Button1Click(Sender: TObject);
 25   private
 26     { Private declarations }
 27     Thread1, Thread2 : TThreadTest;
 28     procedure Thread1Done(Sender : TObject);
 29     procedure Thread2Done(Sender : TObject);
 30 
 31   public
 32     { Public declarations }
 33   end;
 34 
 35 var
 36   Form1: TForm1;
 37   HMutex : THandle = 0;
 38   IncNum : Integer;
 39   GlobalData : Array[1..MaxSize] of Integer;
 40 
 41 implementation
 42 
 43 {$R *.dfm}
 44 
 45 procedure TThreadTest.Execute;
 46 var
 47   i : Integer;
 48   WaitReturn : DWord;
 49 begin
 50   FreeOnTerminate := True;
 51   WaitReturn := WaitForSingleObject(HMutex, INFINITE);
 52   if WaitReturn = Wait_Object_0 then
 53   begin
 54     for i := 1 to MaxSize do
 55     begin
 56       Inc(IncNum);
 57       GlobalData[i] := IncNum;
 58       Sleep(10);
 59     end;
 60   end;
 61 end;
 62 
 63 procedure TForm1.Thread1Done(Sender : TObject);
 64 var
 65   i : Integer;
 66 begin
 67   Memo1.Lines.Clear;
 68   for i:= 1 to MaxSize do
 69   begin
 70     Memo1.Lines.Add(IntToStr(GlobalData[i]));
 71   end;
 72   ReleaseMutex(HMutex);
 73 end;
 74 
 75 procedure TForm1.Thread2Done(Sender : TObject);
 76 var
 77   i : Integer;
 78 begin
 79   Memo2.Lines.Clear;
 80   for i:= 1 to MaxSize do
 81   begin
 82     Memo2.Lines.Add(IntToStr(GlobalData[i]));
 83   end;
 84   ReleaseMutex(HMutex);
 85 end;
 86 
 87 procedure TForm1.FormCreate(Sender: TObject);
 88 begin
 89   HMutex := CreateMutex(nil, False, nil);
 90 end;
 91 
 92 procedure TForm1.FormDestroy(Sender: TObject);
 93 begin
 94   CloseHandle(HMutex);
 95 end;
 96 
 97 procedure TForm1.Button1Click(Sender: TObject);
 98 begin
 99   Thread1 := TThreadTest.Create(False);
100   Thread1.OnTerminate := Thread1Done;
101   Thread2 := TThreadTest.Create(False);
102   Thread2.OnTerminate := Thread2Done;
103 end;
104 
105 end.

 

上面的执行结果如下图:

没有达到预想的效果,预想的效果如下图:

这就说明了,没有达到线程同步的效果,那么是不是互斥对象的效果也没有达到呢?

其实互斥对象的效果已经到达了,只不过Thread2在执行Execute的时候WaitForSingleObject函数返回的是WAIT_ABANDONED

所以没有执行下面的循环,GlobalData数组仍然是Thread1执行后的结果。

WAIT_ABANDONED 的含义如下

指定的对象是互斥对象,并且拥有这个互斥对象的线程在没有释放此对象之前就已终止。此时就称互斥对象被抛弃。这种情况下,这个互斥对象归当前线程所有,并将它设为不发信号状态。

这就说明,建立的互斥对象在没有执行ReleaseMutex之前就被终止了。所以Thread2调用WaitForSingleObject函数的时候就返回WAIT_ABANDONED。

所以要线程正确同步就必须把ReleaseMutex函数放在Execute里面

修改如下

 

procedure TThreadTest.Execute;
var
  i : Integer;
  WaitReturn : DWord;
begin
  FreeOnTerminate :
= True;
  WaitReturn :
= WaitForSingleObject(HMutex, INFINITE);
  
if WaitReturn = Wait_Object_0 then
  
begin
    
for i := 1 to MaxSize do
    
begin
      Inc(IncNum);
      GlobalData[i] :
= IncNum;
      Sleep(
10);
    
end;
  
end;
  ReleaseMutex(HMutex);
end;

 

并且把Thread1Done过程和Thread2Done过程中的ReleasMutex删除

这样就达到了线程同步的效果。

 

不过,具体为什么互斥对象在Thread1线程中使用后,就被自动终止了,导致Thread2使用WaitForSingleObject函数返回WAIT_ABANDONED这一点。我仍不理解,还请大家多多指教

 

posted on 2010-06-25 16:47  若不是因为你  阅读(753)  评论(2编辑  收藏  举报