程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 學習筆記:delphi多線程知識,delphi多線程

學習筆記:delphi多線程知識,delphi多線程

編輯:Delphi

學習筆記: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代碼塊很像,這樣寫起線程同步要簡化不少。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved