多線(xiàn)程編程(8) - 多線(xiàn)程同步之 CriticalSection(臨界區)
先看一段程序, 代碼文件:unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
ListBox1: TListBox;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function MyThreadFun(p: Pointer): DWORD; stdcall;
var
i: Integer;
begin
for i := 0 to 99 do Form1.ListBox1.Items.Add(IntToStr(i));
Result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ID: DWORD;
begin
CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);
CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);
CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ListBox1.Align := alLeft;
end;
end.
窗體文件:object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 154
ClientWidth = 214
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object ListBox1: TListBox
Left = 9
Top = 9
Width = 121
Height = 97
ItemHeight = 13
TabOrder = 0
end
object Button1: TButton
Left = 131
Top = 112
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 1
OnClick = Button1Click
end
end
在這段程序中, 有三個(gè)線(xiàn)程幾乎是同時(shí)建立, 向窗體中的 ListBox1 中寫(xiě)數據, 最后寫(xiě)出的結果是這樣的:

能不能讓它們別打架, 一個(gè)完了另一個(gè)再來(lái)? 這就要用到多線(xiàn)程的同步技術(shù).
前面說(shuō)過(guò), 最簡(jiǎn)單的同步手段就是 "臨界區".
先說(shuō)這個(gè) "同步"(Synchronize), 首先這個(gè)名字起的不好, 我們好像需要的是 "異步"; 其實(shí)異步也不準確...
管它叫什么名字呢, 它的目的就是保證不**、有次序、都發(fā)生.
"臨界區"(CriticalSection): 當把一段代碼放入一個(gè)臨界區, 線(xiàn)程執行到臨界區時(shí)就獨占了, 讓其他也要執行此代碼的線(xiàn)程先等等; 這和前面用的 Lock 和 UnLock 差不多; 使用格式如下:
var CS: TRTLCriticalSection; {聲明一個(gè) TRTLCriticalSection 結構類(lèi)型變量; 它應該是全局的}
InitializeCriticalSection(CS); {初始化}
EnterCriticalSection(CS); {開(kāi)始: 輪到我了其他線(xiàn)程走開(kāi)}
LeaveCriticalSection(CS); {結束: 其他線(xiàn)程可以來(lái)了}
DeleteCriticalSection(CS); {刪除: 注意不能過(guò)早刪除}
//也可用 TryEnterCriticalSection 替代 EnterCriticalSection.
用上臨界區, 重寫(xiě)上面的代碼, 運行效果圖:

代碼文件:unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
ListBox1: TListBox;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
CS: TRTLCriticalSection;
function MyThreadFun(p: Pointer): DWORD; stdcall;
var
i: Integer;
begin
EnterCriticalSection(CS);
for i := 0 to 99 do Form1.ListBox1.Items.Add(IntToStr(i));
LeaveCriticalSection(CS);
Result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ID: DWORD;
begin
CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);
CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);
CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ListBox1.Align := alLeft;
InitializeCriticalSection(CS);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
DeleteCriticalSection(CS);
end;
end.
聯(lián)系客服