多线程最简单的同步手段——"临界区"(CriticalSection): (保证不冲突、有次序、都发生

当把一段代码放入一个临界区, 线程执行到临界区时就独占了, 让其他也要执行此代码的线程先等等; 这和前面用的 Lock UnLock 差不多; 使用格式如下:

var CS: TRTLCriticalSection;   {声明一个 TRTLCriticalSection 结构类型变量; 它应该是全局的} 
InitializeCriticalSection(CS); 
{初始化} 
EnterCriticalSection(CS);      
{开始: 轮到我了其他线程走开} 
LeaveCriticalSection(CS);      
{结束: 其他线程可以来了} 
DeleteCriticalSection(CS);     
{删除: 注意不能过早删除} 
 
//也可用 TryEnterCriticalSection 替代 EnterCriticalSection.


//用临界区重写后的代码文件: 
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(
nil0, @MyThreadFun, nil0, ID); 
  CreateThread(
nil0, @MyThreadFun, nil0, ID); 
  CreateThread(
nil0, @MyThreadFun, nil0, ID); 
end
 
procedure TForm1.FormCreate(Sender: TObject); 
begin 
  ListBox1.Align := alLeft; 
  InitializeCriticalSection(CS); 
end
 
procedure TForm1.FormDestroy(Sender: TObject); 
begin 
  DeleteCriticalSection(CS); 
end
 
end.


Delphi SyncObjs 单元给封装了一个 TCriticalSection , 用法差不多, 代码如下:

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} 
 
uses SyncObjs; 
 
var 
  CS: TCriticalSection; 
 
function MyThreadFun(p: Pointer): DWORD; stdcall; 
var 
  i: Integer; 
begin 
  CS.Enter; 
  
for i := 0 to 99 do Form1.ListBox1.Items.Add(IntToStr(i)); 
  CS.Leave; 
  Result := 
0
end
 
procedure TForm1.Button1Click(Sender: TObject); 
var 
  ID: DWORD; 
begin 
  CreateThread(
nil0, @MyThreadFun, nil0, ID); 
  CreateThread(
nil0, @MyThreadFun, nil0, ID); 
  CreateThread(
nil0, @MyThreadFun, nil0, ID); 
end
 
procedure TForm1.FormCreate(Sender: TObject); 
begin 
  ListBox1.Align := alLeft; 
  CS := TCriticalSection.Create; 
end
 
procedure TForm1.FormDestroy(Sender: TObject); 
begin 
  CS.Free; 
end
 
end.