临界区是一段代码,一次只允许一个线程执行这段代码。当把一段代码放入一个临界区, 线程执行到临界区时就独占了, 其他线程如果要访问这段代码,一定要等前一个访问的线程结束才行。借用前面的比喻比作图书馆,临界区就像把图书馆设计成只有一个位置(现实中好像不太合理,不管了,反正这么个意思),当有一个人正在办理业务时,其他人只能等待那个人办完业务才能进去。
使用临界区的步骤:
1、声明一个TRLCriticalSection记录类型的变量如CS,必须是全局的;
2、使用前先初始化:InitializeCriticalSection(CS);
3、EnterCriticalSection(CS); 线程进入临界区,其他线程需要等待
4、LeaveCriticalSection(CS); 线程离开临界区,其他线程可以访问了
5、DeleteCriticalSection(CS); 最后删除临界区
重写前文的例子,如下:
{主窗体代码}
- unit Unit2;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls;
- type
- TForm2 = class(TForm)
- ListBox1: TListBox;
- Button1: TButton;
- procedure Button1Click(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
- var
- Form2: TForm2;
- CS:TRTLCriticalSection; //全局临界区变量
- implementation
- uses MyThread;
- {$R *.dfm}
- procedure TForm2.Button1Click(Sender: TObject);
- begin
- TMyThread.Create(False);
- TMyThread.Create(False);
- TMyThread.Create(False);
- end;
- procedure TForm2.FormCreate(Sender: TObject);
- begin
- InitializeCriticalSection(CS); //初始化
- end;
- procedure TForm2.FormDestroy(Sender: TObject);
- begin
- DeleteCriticalSection(CS); //删除
- end;
- end.{线程类}
- unit MyThread;
- interface
- uses
- Classes,StdCtrls,SysUtils,Windows;
- type
- TMyThread = class(TThread)
- private
- { Private declarations }
- str:String;
- procedure AddList;
- protected
- procedure Execute; override;
- end;
- implementation
- uses Unit2;
- { TMyThread }
- procedure TMyThread.AddList;
- begin
- Form2.ListBox1.Items.Add(str);
- end;
- procedure TMyThread.Execute;
- var
- i:Integer;
- begin
- { Place thread code here }
- FreeOnTerminate:=True;
- EnterCriticalSection(CS); //进入临界区
- try
- for i := 0 to 99 do
- begin
- if not Terminated then
- begin
- str:=Format('线程ID:%.4d,第%.2d个循环。',[GetCurrentThreadId,i]);
- Synchronize(AddList);
- end;
- end;
- finally
- LeaveCriticalSection(CS); //离开临界区
- end;
- end;
- end.
OK,可以看到线程是依次执行的了。
临界区只用于进程内,是相当轻量级的,当没有线程冲突时,进入或离开临界区大概只需要10到20个时钟周期