• 转:学习笔记:delphi多线程学识


    学习笔记:delphi多线程知识
    最近一直在温习旧的知识,刚好学习了一下Java的线程安全方面的知识,今天想起之前一直做的Delphi开发,所以还是有必要温习一下,看看这些不同的编程语言有什么不同之处。
     
    Delphi的线程同步方法:
    1、临界区
    申明一个临界资源
    FLock   : TRTLCriticalSection;
    先初化一个临界资源对象
    InitializeCriticalSection(FLock)
    销毁临界资源对象
    DeleteCriticalSection(FLock)
    procedure TSaveThread.PushTask(pTask: pFileInfo);
    begin
      //进入临界资源,有线程占用后,后面的线程会阻塞
      EnterCriticalSection(FLock);
      try
        //这里是受保护的代码
        if not Assigned(FTasks) then
          FTasks:= TList.Create;
    
        FTasks.Add(pTask);
      finally
        //离开临界资源,其他的阻塞的线程可以进入
        LeaveCriticalSection(FLock);
      end;
    end;
    这种方式还是挺简单的,和Java中的synchronized代码块方式类似
    2、Event事件
    Event有两种状态:有信号和无信号,通过这个特性可以用于线程同步。Event相关的API也多,控制起来也比较灵活,看看他的几个方法:
    CreateEvent:创建事件
    SetEvent:设置为有信号状态
    ResetEvent: 设置为无信号状态
    PulseEvent :设置为有信号状态,接着又设置为无信号状态(有点类似于单步调试的感觉)
    在线程中还是要用WaitForSingleObject来阻塞
    procedure TSearchTopNThread.Execute;
    begin
      while not Self.Terminated do
      begin
        WaitForSingleObject(FEvent, INFINITE);//FEvent为无信号时阻塞,直到变为有信号时代码继续执行
        .......
      end;
    end;
    //设置事件状态为无信号,阻塞线程
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      ResetEvent(hEvent);
    end;
    
    //设置事件状态为有信号,线程解除阻塞
    procedure TForm1.Button2Click(Sender: TObject);
    begin
      SetEvent(hEvent);
    end;
    
    //设置一次脉冲信号状态,先设置有信号,再设置无信号
    procedure TForm1.Button3Click(Sender: TObject);
    begin
      PulseEvent(hEvent);
    end;
     
     
    3、互斥对象
    var  hMutex: THandle; //互斥对象的句柄
    
    function ThreadFun(p: Pointer): DWORD; stdcall;
    var
      i: Integer;
    beginfor i := 0 to 1000 do
      begin
        //使用WaitForSingleObject访问互斥对象,如果hMutex为被锁定>=1,那就等待,如果为未锁定那么就给hMutex的上锁,然后运行下面的代码
        if WaitForSingleObject(hMutex, INFINITE) = WAIT_OBJECT_0 then
        begin      //保护中的代码
          .....
          
          //代码结束后释放信号量,表示当前线程已经完成处理,后面的线程就可以获得控制权
          ReleaseMutex(hMutex);
        end;
      end;
      Result := 0;
    end;
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      hMutex := CreateMutex(nil, False, nil);//第二个参数为False表示创建的互斥对象不被任何线程拥有,也就说初始状态为未锁定,线程可以占有
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      CloseHandle(hMutex);
    end;
    
    end.
    总的过程和临界区有些类似,只不过互斥对象是系统核心对象,可以跨进程,而临界区只是当前进程。有这个特性可以用于对文件等资源的并发保护。
    4、信号量
     信号量与互斥对象的方法类似,信号量的特点是可以设置计数,就是同时可以允许多个线程同时访问同一段代码。互斥对象就是信号量为1的情况,后面的线程只能等前一个执行完,而信号量就可以允许指定多个执行。
     
     
    后来在看TThread的代码时发现新的Delphi版本中有了一个好东西:TMnitor
    try
          TMonitor.Enter(ThreadLock);
          try
            SyncProcPtr.Queued := QueueEvent;
            if SyncList = nil then
              SyncList := TList.Create;
            SyncProcPtr.SyncRec := ASyncRec;
            SyncList.Add(SyncProcPtr);
            SignalSyncEvent;
            if Assigned(WakeMainThread) then
              WakeMainThread(SyncProcPtr.SyncRec.FThread);
            if not QueueEvent then
              TMonitor.Wait(SyncProcPtr.Signal, ThreadLock, INFINITE)
          finally
            TMonitor.Exit(ThreadLock);
          end;
    这个代码和java中的Synchronized代码块很像,这样写起线程同步要简化不少。
  • 相关阅读:
    ----localStorage的同步与异步----
    ----vue2.0实现别人通过ip访问自己运行的项目----
    ----vue之搜索框与防抖函数的封装----
    ----vue项目打包之浏览器存在缓存问题----
    ----vue组件name的作用小结----
    ----HTML5本地储存--利用storage事件实时监听Web Storage----
    ---- vue之filter ----
    ----vue项目配置环境----
    ----git-ssh 配置和使用----
    python『学习之路03』装饰器
  • 原文地址:https://www.cnblogs.com/rogge7/p/5960934.html
Copyright © 2020-2023  润新知