求教:同样的多线程程序,分别用临界区和互斥对象,结果却不同(50分)

  • 主题发起人 主题发起人 wind_2005
  • 开始时间 开始时间
W

wind_2005

Unregistered / Unconfirmed
GUEST, unregistred user!
各位大侠:
我今天做两个简单的多线程程序,这两个程序,除了同步方式不同,萁他所有代码都相同,但处理后的结果却不同。这两个程序看起来代码虽长,其实功能很简单,还望各位高人有空能帮我看看,谢谢了!
代码如下:
===================
第一个程序:
===================
unit Unit1;

interface

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


type
TForm1 = class(TForm)
ListBox1: TListBox;
ListBox2: TListBox;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
Thread1: TSyncThread;
Thread2: TSyncThread;
procedure Thread1Done(Sender: TObject);
procedure Thread2Done(Sender: TObject);
{ Private declarations }
public
{ Public declarations }
end;


const
MaxSize = 100;

var
Form1: TForm1;
CS: TRTLCriticalSection
//临界区变量
GData: array[1..MaxSize] of integer;
iNum: integer;


implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
InitializeCriticalSection(CS)
//初始化临界区
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
DeleteCriticalSection(CS)
//清除临界区
end;

procedure TForm1.Thread1Done(Sender: TObject);
var
i: integer;
begin
ListBox1.Clear;

for i := 1 to MaxSize do
begin
ListBox1.Items.Add(IntToStr(gdata));
end;
LeaveCriticalSection(CS)
//离开临界区

end;

procedure TForm1.Thread2Done(Sender: TObject);
var
i: integer;
begin
ListBox2.Clear;

for i := 1 to MaxSize do
begin
ListBox2.Items.Add(IntToStr(gdata));
end;
LeaveCriticalSection(CS)
//离开临界区

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Thread1 := TSyncThread.Create(False);
Thread1.OnTerminate := Thread1Done;
Thread2 := TSyncThread.Create(False);
Thread2.OnTerminate := Thread2Done;
end;

end.
--------------------
unit Unit2;

interface

uses
Classes, sysUtils, windows;

type
TSyncThread = class(TThread)
private
{ Private declarations }
protected
procedure Execute
override;
end;

implementation

uses Unit1;

{ Important: Methods and properties of objects in VCL or CLX can only be used
in a method called using Synchronize, for example,

Synchronize(UpdateCaption);

and UpdateCaption could look like,

procedure TSyncThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end
}

{ TSyncThread }

procedure TSyncThread.Execute;
var
i: integer;
begin
FreeOnTerminate := True;
EnterCriticalSection(CS)
//进入临界区
for i := 1 to MaxSize do
begin
Inc(iNum);
GData := iNum;
sleep(5);
end;


end;

end.



===================
第二个程序:
===================
unit Unit1;

interface

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


type
TForm1 = class(TForm)
ListBox1: TListBox;
ListBox2: TListBox;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
Thread1: TSyncThread;
Thread2: TSyncThread;
procedure Thread1Done(Sender: TObject);
procedure Thread2Done(Sender: TObject);
{ Private declarations }
public
{ Public declarations }
end;


const
MaxSize = 100;

var
Form1: TForm1;
HMutex: THandle
//互斥对象句柄
GData: array[1..MaxSize] of integer;
iNum: integer;


implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
HMutex := CreateMutex(nil,False,nil)
//创建互斥对象
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
CloseHandle(HMutex)
//释放互斥对象
end;

procedure TForm1.Thread1Done(Sender: TObject);
var
i: integer;
begin
ListBox1.Clear;

for i := 1 to MaxSize do
begin
ListBox1.Items.Add(IntToStr(gdata));
end;
ReleaseMutex(HMutex)
//解除互斥

end;

procedure TForm1.Thread2Done(Sender: TObject);
var
i: integer;
begin
ListBox2.Clear;

for i := 1 to MaxSize do
begin
ListBox2.Items.Add(IntToStr(gdata));
end;
ReleaseMutex(HMutex)
//解除互斥

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Thread1 := TSyncThread.Create(False);
Thread1.OnTerminate := Thread1Done;
Thread2 := TSyncThread.Create(False);
Thread2.OnTerminate := Thread2Done;
end;

end.
-------------------
unit Unit2;

interface

uses
Classes, sysUtils, windows;

type
TSyncThread = class(TThread)
private
{ Private declarations }
protected
procedure Execute
override;
end;

implementation

uses Unit1;

{ Important: Methods and properties of objects in VCL or CLX can only be used
in a method called using Synchronize, for example,

Synchronize(UpdateCaption);

and UpdateCaption could look like,

procedure TSyncThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end
}

{ TSyncThread }

procedure TSyncThread.Execute;
var
i: integer;
WaitReturn: DWord;
begin
FreeOnTerminate := True;

WaitReturn := WaitForSingleObject(HMutex, INFINITE)
//进入同步
if WaitReturn = wait_Object_0 then
for i := 1 to MaxSize do
begin
Inc(iNum);
GData := iNum;
sleep(5);
end;


end;

end.
------------------



不知是我的代码写错了,还是本该是这样的结果?为什么?
谢谢!
 
这两个程序其实是同一个程序,只是多线程的同步方式不同。
在窗体中其实只有一个Button和两个ListBox,
只需要建立一个窗体和一个存放线程类的Unit,然后把上面的代码复制,替换原有代码即可运行。

还望大家帮我看看,
谢了!
 
结果怎么都没说?
 
第一个程序,用临界区时,第一个ListBox中显示了1至100,第二个ListBox中显示了101至200,

第二个程序,用互斥对象时,第一个ListBox中显示了1至100,第二个ListBox中却同样显示了1至100,
 
自己顶一下了[:(]
 
不太明白你的程序的功能.

多线程式的程序本来就是不可预知的.
 
自己再顶一下了,希望那位朋友能帮忙看看。
 
[:(]谁能帮我?
 
多人接受答案了。
 
真是不好意思,今天运动会,没有时间回帖。
你的问题研究了一下,关键在于互斥对象的使用方法不对。

互斥对象的WaitForSingleObject和ReleaseMutex必须在一个线程中配套使用,
你原来的ReleaseMutex是在Done事件,也就是在主线程中使用的。

将其放到线程的Execute最后调用就可以了。

你如果非要在以界面上的同步问题,可以调用Syncronize函数。
 
这是Delphi中的注释:
The ReleaseMutex function fails if the calling thread does not own the mutex object.
A thread gets ownership of a mutex by specifying a handle of the mutex in one of the wait functions. The thread that creates a mutex object can also get immediate ownership without using one of the wait functions. When the owning thread no longer needs to own the mutex object, it calls the ReleaseMutex function.
While a thread has ownership of a mutex, it can specify the same mutex in additional wait-function calls without blocking its execution. This prevents a thread from deadlocking itself while waiting for a mutex that it already owns. However, to release its ownership, the thread must call ReleaseMutex once for each time that the mutex satisfied a wait.

请注意:
When the owning thread no longer needs to own the mutex object, it calls the ReleaseMutex function.

是Owning Thread调用ReleaseMutex
 
后退
顶部