Delphi Thread互斥量和事件

互斥量是系统内核对象,谁拥有就谁执行。它与临界区工作很类似。
  不同处在于:
  1、互斥量可以跨进程边界同步线程。
  2、可以给互斥量取个名字,通过引用互斥量的名字来使用一个已知的互斥量对象。
     使用互斥量之类的对象需要反复调用系统内核,期间需要进行进程上下文转换和控制级别转换,大概需要耗费400到600个时间周期。
     又是图书馆的比喻,现在是搞一个锁,把钥匙(互斥量句柄)交给管理员(操作系统),每一个人(线程)想要借书的时候,都要向管理员拿钥匙。当有人在使用的时候,另一人必须等待,等到钥匙有空的时候(互斥量进入信号状态),才能拿到钥匙(拥有了句柄)办理借书业务(此时互斥量进入非信号状态直到办完业务)。
     使用互斥量的步骤:
      1、声明一个全局的互斥量句柄变量(var hMutex: THandle;);
      2、创建互斥量:CreateMutex(
                                lpMutexAttributes: PSecurityAttributes;
                                bInitialOwner: BOOL;
                                lpName: PWideChar   ): THandle;
        (lpMutexAttributes参数:指向TSecurityAttributes的指针,安全属性,一般用缺省安全属性nil;
          bInitialOwer参数:表示创建的互斥量线程是否是互斥量的属主,如果该参数为False互斥量就没属主,一般来讲应设为False,否则如果设为True的话,要当主线程结束其他线程才成为它的属主才能运行;
         lpName参数:是互斥量的名字,若打算取名的话,则传入nil。)
      3、用等待函数控制线程进入同步代码块:WaitForSingleObject(
                                                                  hHandle:THandel;
                                                                 dwMilliseconds:DWORD):DWORD;
      (hHandel参数:是对象的句柄,不同对象信号状态不同,对于互斥量而言当没有线程占有时,互斥量就时入信号状态;
         dwMilliseconds参数:可以是一个时间段,可以是0表示仅检查对象状态后立即返回,可以是INFINITE值表示函数一直等待直到对象进入信号状态;
      返回值常量如下:WAIT_ABANDONED指定的对象是互斥量对象,拥有这个互斥量对象的线程在没有释放互斥量之前就已经终止,称作废弃互斥量,此时该互斥量归调用线程所拥有,并把这个互斥量设为非信号状态;WAIT_OBJECT_0指定对象的进入信号状态;WAIT_TIMEOUT等待时间已过,对象状态依然是无信号状态)
      4、执行线程运行代码。
      5、线程运行完后释放互斥量的拥有权:ReleaseMutex(hMutex: THandle);

      6、最后关闭互斥量:CloseHandle(hMutex: THandle);


自定义线程:

{线程类}
unit CustomThread;

interface

uses
  Classes,StdCtrls,SysUtils,Windows;

type

  TEventThread = class(TThread)
  private
    FLabel:TLabel;
    str:String;
    procedure Show;
  protected
    procedure Execute; override;
  public
    Constructor Create(aLabel:TLabel);
  end;

  TMutexThread = class(TThread)
  private
    FLabel:TLabel;
    str:String;
    procedure Show;
  protected
    procedure Execute; override;
  public
    Constructor Create(aLabel:TLabel);
  end;

implementation

uses DemoMain;

{ TEventThread }

constructor TEventThread.Create(aLabel: TLabel);
begin
  FLabel:=aLabel;
  Inherited Create(False);
end;

procedure TEventThread.Execute;
var
  i:Integer;
begin
  FreeOnTerminate:=True;
  for i := 0 to 2000 do
  begin
    Sleep(5);
    if WaitForSingleObject(hEvent,INFINITE)=WAIT_OBJECT_0 then
      begin
       if not Terminated then
        begin
          str:=Format('线程ID:%.4d,第%.4d个循环。',[GetCurrentThreadId,i]);
          Synchronize(Show);  // 线程调用vcl控件,必须要用Synchronize,否则会出错
        end;
      end;
  end;
end;

procedure TEventThread.Show;
begin
  FLabel.Caption:=str;
end;

{ TMutexThread }

procedure TMutexThread.Show;
begin
  FLabel.Caption:=str;
end;

Constructor TMutexThread.Create(aLabel: TLabel);
begin
  FLabel:=aLabel;
  Inherited Create(False);
end;

procedure TMutexThread.Execute;
var
  i:Integer;
begin
//  if WaitForSingleObject(hMutex,INFINITE)=WAIT_OBJECT_0 then
//  begin
//   try
//      for i := 0 to 2000 do
//      Sleep(5);
//      begin
//        if not Terminated then
//          begin
//            str:=Format('线程ID:%.4d,第%.2d个循环。',[GetCurrentThreadId,i]);
//            Synchronize(Show);
//          end;
//      end;
//   finally
//    ReleaseMutex(hMutex);
//   end;
//  end;
  for i := 0 to 2000 do
  begin
    Sleep(5);
    if WaitForSingleObject(hMutex,INFINITE)=WAIT_OBJECT_0 then
    begin
      try
        if not Terminated then
        begin
          str:=Format('线程ID:%.4d,第%.2d个循环。',[GetCurrentThreadId,i]);
          Synchronize(Show);
        end;
      finally
        ReleaseMutex(hMutex);
      end;
    end;
  end;

end;

end.

主Form调用:

type

  TWorkMode = (wmEvent, wmMutex);

  TFormMain = class(TForm)
    Panel1: TPanel;
    GroupBox1: TGroupBox;
    Panel2: TPanel;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    btnPulseEvent: TButton;
    btnResetEvent: TButton;
    btnSetEvent: TButton;
    Button1: TButton;
    GroupBox2: TGroupBox;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure btnSetEventClick(Sender: TObject);
    procedure btnPulseEventClick(Sender: TObject);
    procedure btnResetEventClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  FormMain: TFormMain;
  hEvent:THandle;
  hMutex:THandle;

implementation

{$R *.dfm}

uses CustomThread;

procedure TFormMain.btnPulseEventClick(Sender: TObject);
begin
  PulseEvent(hEvent); //PulseEvent(执行一次后立即暂停)
end;

procedure TFormMain.btnResetEventClick(Sender: TObject);
begin
  ResetEvent(hEvent); // ResetEvent(暂停运行)
end;

procedure TFormMain.btnSetEventClick(Sender: TObject);
begin
  SetEvent(hEvent);  //SetEvent(启动运行)
end;

procedure TFormMain.Button1Click(Sender: TObject);
begin
  TEventThread.Create(Label1);
  TEventThread.Create(Label2);
  TEventThread.Create(Label3);
  TEventThread.Create(Label4);
  TEventThread.Create(Label5);
end;

procedure TFormMain.Button2Click(Sender: TObject);
begin
  TMutexThread.Create(Label1);
  TMutexThread.Create(Label2);
  TMutexThread.Create(Label3);
  TMutexThread.Create(Label4);
  TMutexThread.Create(Label5);
end;

procedure TFormMain.FormCreate(Sender: TObject);
begin
{ lpEventAttributes参数,指向TSecurityAttributes记录的指针,一般可以缺省填入nil值;
   bManualReset参数,是否可手动暂停,True为可手动,False为事件对象控制一次后将立即暂停;
   bInitialState参数,初始状态,True为事件对象创建后处可运行状态,False为暂停状态;
   lpName参数,事件的名称;
   返回值为句柄。}
  hEvent:=CreateEvent(nil,True,True,nil);

  hMutex:=CreateMutex(nil,false,'MyThreadDemo');
end;

procedure TFormMain.FormDestroy(Sender: TObject);
begin
  CloseHandle(hEvent);
  CloseHandle(hMutex);
end;

源代码下载: ThreadDemo.rar


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值