在使用多线程的时候,如果多线程对某个特定的公共数据或资源进行访问,需要对多线程进行协调操作,叫做线程同步。
例如:三个线程分别循环地向ListBox中写入数据。没有进行同步时,写入的顺序是不确定的。
- 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);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
- var
- Form2: TForm2;
- implementation
- uses MyThread;
- {$R *.dfm}
- procedure TForm2.Button1Click(Sender: TObject);
- begin
- TMyThread.Create(False);
- TMyThread.Create(False);
- TMyThread.Create(False);
- 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 }
- for i := 0 to 99 do
- begin
- if not Terminated then
- begin
- str:=Format('线程ID:%d,第%d个循环。',[GetCurrentThreadId,i]);
- Synchronize(AddList);
- end;
- end;
- end;
- end.
三个线程根据分配到的CPU时间的顺序向ListBox中写入数据。这里的公共资源是ListBox。
可以将这个公共的冷资源比喻为一个图书馆,线程比喻为借书看书的人员。那么没有同步处理的情况下,就好像图书馆完全开放,没有人管理,每个人都可以访问这个图书馆。看起来乱糟糟的,而且当某人想借书A的话,查询的时候书A还在,当他去借的时候可能被另一人已借走。
为了更好管理的需要(某些对公共资源的访问必须逐个线程处理,才不会出错),这里就要用到同步,即查询和借书这两个步骤要一起完成,等一个人完成以后,才接受另一个人的请求。
接下来介绍线程同步的几种手段:临界区、互斥量、信号量、事件。