篇幅的原因,我截取其中的一段结果,但是已经足以说明问题所在
解决方案对于我们自己来说解决起来好像确实很麻烦,好在我们的前辈已经提供了解决方案 。不学不知道,一学吓一跳,Delphi针对线程安全问题提供了不止一种解决方案 。
临界区临界区是一种最直接的线程同步方式 。所谓临界区,简单的说就是有一块区域,而在该区域内的代码只能有一个线程在执行 。针对临界区的使用Delphi中有两种方式使用EnterCriticalSection( ) 和LeaveCriticalSection( ) API 函数,另外一种是使用 TCriticalSection 类,我个人推荐使用TCriticalSection 因为该类对API进行了封装使用更为便捷 。所在的单元为“SyncObjs”
在理清临界区的概念之后我们改组上述代码
program Project1;{$APPTYPE CONSOLE}{$R *.res}usesSyncObjs, System.SysUtils, System.Classes;typeTWorkThread = class(TThread)protectedprocedure Execute; override;publicend;var// 定义全局变量,充当共享数据Num: Integer = 0;var{ 声明临界 }CS: TCriticalSection;{ TWorkThread }procedure TWorkThread.Execute;begin// 循环的方式自增Numwhile True do beginTThread.Sleep(100);// 临界区开始CS.Enter;// 当Num的值大于10则终止线程if (Num > 10) thenExit;Writeln(TThread.CurrentThread.ThreadID.ToString + ':' + Num.ToString);Inc(Num);// 临界区结束CS.Leave;end;end;begin//初始化临界区CS := TCriticalSection.Create;TWorkThread.Create(False);TWorkThread.Create(False);TWorkThread.Create(False);Readln;end.互斥对象uses SyncObjs;用TMutex类的方法处理(把释放语句放在循环内外可以决定执行顺序)
例:互斥输出三个0~2000的数字到窗体在不同位置 。
unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls;typeTMyThread = class(TThread)private{ Private declarations }protectedprocedure Execute; override; {执行}procedure Run;{运行}end;TForm1 = class(TForm)btn1: TButton;procedure FormDestroy(Sender: TObject);procedure btn1Click(Sender: TObject);private{ Private declarations }public{ Public declarations }end;varForm1: TForm1;implementation{$R *.dfm}uses SyncObjs;varMyThread:TMyThread;{声明线程}Mutex:TMutex; {声明互斥体}f:integer;procedure TMyThread.Execute;begin{ Place thread code here }FreeOnTerminate:=True; {加上这句线程用完了会自动注释}Run;{运行}end;procedure TMyThread.Run;vari,y:integer;beginInc(f);y:=20*f;for i := 0 to 2000dobeginif Mutex.WaitFor(INFINITE)=wrSignaled then{判断函数,能用时就用}beginForm1.Canvas.Lock;Form1.Canvas.TextOut(10,y,IntToStr(i));Form1.Canvas.Unlock;Sleep(1);Mutex.Release; {释放,谁来接下去用}end;end;end;procedure TForm1.btn1Click(Sender: TObject);beginf:=0;Repaint;Mutex:=TMutex.Create(False);{参数为是否让创建者拥有该互斥体,一般为False}MyThread:=TMyThread.Create(False);MyThread:=TMyThread.Create(False);MyThread:=TMyThread.Create(False);end;procedure TForm1.FormDestroy(Sender: TObject);beginMutex.Free;{释放互斥体}end;end.Semaphore(信号或叫信号量)unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls;typeTForm1 = class(TForm)Button1: TButton;Edit1: TEdit;procedure Button1Click(Sender: TObject);procedure FormCreate(Sender: TObject);procedure FormDestroy(Sender: TObject);procedure Edit1KeyPress(Sender: TObject; var Key: Char);end;varForm1: TForm1;implementation{$R *.dfm}uses SyncObjs;varf: Integer;MySemaphore: TSemaphore;function MyThreadFun(p: Pointer): DWORD; stdcall;vari,y: Integer;beginInc(f);y := 20 * f;if MySemaphore.WaitFor(INFINITE) = wrSignaled thenbeginfor i := 0 to 1000 dobeginForm1.Canvas.Lock;Form1.Canvas.TextOut(20, y, IntToStr(i));Form1.Canvas.Unlock;Sleep(1);end;end;MySemaphore.Release;Result := 0;end;procedure TForm1.Button1Click(Sender: TObject);varThreadID: DWORD;beginif Assigned(MySemaphore) then MySemaphore.Free;MySemaphore := TSemaphore.Create(nil, StrToInt(Edit1.Text), 5, ''); {创建,参数一为安全默认为nil,参数2可以填写运行多少线程,参数3是运行总数,参数4可命名用于多进程}Self.Repaint;f := 0;CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);end;{让 Edit 只接受 1 2 3 4 5 五个数}procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);beginif not CharInSet(Key, ['1'..'5']) then Key := #0;end;procedure TForm1.FormCreate(Sender: TObject);beginEdit1.Text := '1';end;procedure TForm1.FormDestroy(Sender: TObject);beginif Assigned(MySemaphore) then MySemaphore.Free;end;end.Event (事件对象)注:相比API的处理方式,此类没有启动步进一次后暂停的方法 。
以上关于本文的内容,仅作参考!温馨提示:如遇健康、疾病相关的问题,请您及时就医或请专业人士给予相关指导!
「四川龙网」www.sichuanlong.com小编还为您精选了以下内容,希望对您有所帮助:- 电脑桌面字体大小设置方法 win10添加字体在哪里设置
- java开发需要掌握的技术 java开发平台有哪些
- webpack5和4的区别 webpack使用教程
- java项目开发实例 java系统架构有哪些
- 投诉物业收费不开发票的举报信怎么写最管用?
- vim配置c语言开发环境 vim简单配置教程
- 团油app加油靠谱吗?团油app是哪个公司开发的?
- 国家开发银行助学贷款信息网 国家开发银行生源地助学贷款系统
- 自己做游戏软件的app推荐 app游戏开发需要多少钱
- 十分钟配置Mac OS主题 ubuntu桌面美化mac