1、临界区
一次只能由一个线程来执行的一段代码。
2、互斥
互斥非常类似于临界区,除了两个关键的区别:首先,互斥可用于跨进程的线程同步。其次,互斥能被赋予一个字符串名字,并且通过引用此名字创建现有互斥对象的附加句柄。
临界区与事件对象(如互斥对象)的最大区别是在性能上。临界区在没有线程冲突时,要用10-15个时间片,而事件对象由于涉及到系统内核要用400-600个时间片。
3、信号量
它是在互斥的基础上建立的,但信号量增加了资源计数的功能,预定数目的线程允许同时进入要同步的代码。
{*******************************************************}
{ }
{ 多线程同步演示代码 }
{ }
{ 版权所有 (C) 2010 风林 }
{ }
{*******************************************************}
unit untMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
btnStart: TButton;
procedure btnStartClick(Sender: TObject);
private
procedure ThreadsDone(Sender:TObject);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
CS:TRTLCriticalSection; //临界区记录
hMutex:THandle = 0; //互斥句柄
hSem:THandle = 0;//信号量句柄
DoneFlags:Integer = 0;
threadvar//线程局部变量
GlobalStr:string;
type
TTLSThread = class(TThread)
private
FNewStr:string;
protected
procedure Execute;override;
public
constructor Create(const ANewStr:string);
end;
procedure SetShowStr(const S:string);
begin
if S = '' then
MessageBox(0,PChar(GlobalStr),'The string is...',MB_OK)
else
GlobalStr := S;
end;
{ TTLSThread }
constructor TTLSThread.Create(const ANewStr: string);
begin
FNewStr := ANewStr;
inherited Create(False);
end;
procedure TTLSThread.Execute;
var
WaitReturn:DWORD;
begin
OnTerminate := Form1.ThreadsDone; //线程结束时执行相应清理代码
FreeOnTerminate := True; //自动释放资源
//EnterCriticalSection(CS); //进入临界区
WaitReturn := WaitForSingleObject(hSem,INFINITE);//计数器减1
// if WaitForSingleObject(hMutex,INFINITE)= WAIT_OBJECT_0 then
if WaitReturn = WAIT_OBJECT_0 then
begin
SetShowStr(FNewStr);
SetShowStr('');
Sleep(100);
end;
//LeaveCriticalSection(CS);//离开临界区
// ReleaseMutex(hMutex); //解除拥有关系,互斥对象重新进入发信号状态
ReleaseSemaphore(hSem,1,nil);//信号量对象计数加1
end;
procedure TForm1.btnStartClick(Sender: TObject);
begin
// InitializeCriticalSection(CS);//初始化临界区
// hMutex := CreateMutex(nil,False,nil); //创建一个互斥量
hSem := CreateSemaphore(nil,
1, //这个值必须在0和lMaximumCount之间,大于0则表示处理发信号状态
1, //由于只允许个线程进入同步代码,所以设置成1
nil);//
SetShowStr('Hello world');
TTLSThread.Create('Dilbert');
TTLSThread.Create('xx');
TTLSThread.Create('test');
end;
procedure TForm1.ThreadsDone(Sender: TObject);
begin
Inc(DoneFlags);
if DoneFlags = 3 then //当前测试时创建了3个线程
begin
// DeleteCriticalSection(CS); //删除临界区记录信息
//CloseHandle(hMutex);//释放由CreateMutex创建对象的句柄
CloseHandle(hSem);//释放由CreateSemaphore创建对象的句柄
end;
end;
end.