臨界區是一段代碼,一次只允許一個線程執行這段代碼。當把一段代碼放入一個臨界區, 線程執行到臨界區時就獨占了, 其他線程如果要訪問這段代碼,一定要等前一個訪問的線程結束才行。借用前面的比喻比作圖書館,臨界區就像把圖書館設計成只有一個位置(現實中好像不太合理,不管了,反正這么個意思),當有一個人正在辦理業務時,其他人只能等待那個人辦完業務才能進去。
使用臨界區的步驟:
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個時鍾周期
