Delphi中使用TMultiReadExclusiveWriteSynchronizer類進行資料同步

來源:互聯網
上載者:User

原文:http://www.cnblogs.com/94YY/archive/2011/10/05/2199346.html

Delphi中使用TMultiReadExclusiveWriteSynchronizer類進行資料同步

(調試環境:Delphi2007+WinXPsp3 常式:Tst_Thread5.dpr)

前面的例子都是同類線程的不同執行個體來讀寫全域變數,用臨界區、互斥等來鎖住同段代碼。現在碰到的問題是,A,B兩個不同類型的線程,如何安全地來讀寫全域變數。

unit Tst_Thread5U;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,SyncObjs;
type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
  TFirstThread=Class(TThread)
  protected
    procedure Execute;override;
    procedure ShowNum;
  end;
  TSecondThread=Class(TThread)
  protected
    procedure Execute;override;
    procedure ShowNum;
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
const
  MaxSize=12;
var
  WhichRun:integer;
  GlobalArry:array[1..MaxSize] of Integer;
  LockCS:TCriticalSection; //uses SyncObjs
  LockMREWS:TMultiReadExclusiveWriteSynchronizer;  //uses SysUtils
//===============
procedure AddNum;
var
  i,j:integer;
begin
  if WhichRun=2 then LockCS.Acquire;
  if WhichRun=3 then LockMREWS.BeginRead;
  j:=GlobalArry[MaxSize];
  if WhichRun=3 then LockMREWS.EndRead;
  if WhichRun=3 then LockMREWS.BeginWrite;
  for i := 1 to MaxSize do
  begin
    GlobalArry[i]:=j;
    inc(j);
    Sleep(5);
  end;
  if WhichRun=2 then LockCS.Release;
  if WhichRun=3 then LockMREWS.EndWrite;
end;
procedure TFirstThread.Execute;
begin
  FreeOnTerminate:=True;
  AddNum;
  Synchronize(ShowNum);
end;
procedure TFirstThread.ShowNum;
var
  i:integer;
begin
  for i := 1 to MaxSize do
    Form1.Memo1.Lines.Add(inttostr(GlobalArry[i]));
end;
procedure TSecondThread.Execute;
begin
  FreeOnTerminate:=True;
  AddNum;
  Synchronize(ShowNum);
end;
procedure TSecondThread.ShowNum;
var
  i:integer;
begin
  for i := 1 to MaxSize do
    Form1.Memo1.Lines.Add(inttostr(GlobalArry[i]));
end;
//未阻塞
procedure TForm1.Button1Click(Sender: TObject);
begin
  WhichRun:=1;
  TFirstThread.Create(False);
  TSecondThread.Create(False);
end;
//阻塞 TCriticalSection
procedure TForm1.Button2Click(Sender: TObject);
begin
  WhichRun:=2;
  TFirstThread.Create(False);
  TSecondThread.Create(False);
end;
//TMREWS
procedure TForm1.Button3Click(Sender: TObject);
begin
  WhichRun:=3;
  TFirstThread.Create(False);
  TSecondThread.Create(False);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
  LockCS:=TCriticalSection.Create;
  LockMREWS:=TMultiReadExclusiveWriteSynchronizer.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
  LockCS.Free;
  LockMREWS.Free;
end;
end.

一、用TCriticalSection類來阻塞。(ps:這裡的咚咚都涉及Win32編程,我對這些不瞭解,先掌握如何運用吧。)這個有點類似臨界區。要Uses SyncObjs單元。
1、聲明一個全域的TCriticalSection類的執行個體。
2、建立TCriticalSection.Create,最好是在程式onCreate裡面,這樣才能保證對所有線程進行控制。
3、在全域變數訪問前用TCriticalSection.Acquire或TCriticalSection.Enter來阻塞。
4、訪問完畢,用TCriticalSection.Release或TCriticalSection.Leave來解除阻塞。
5、在恰當的位置進行TCriticalSection.Free,一般在程式的onDestroy裡。

二、用TMultiReadExclusiveWriteSynchronizer類來阻塞。可以寫成TMREWSync。這個類在SysUtils單元裡。(ps:天哪,那麼長的單詞我第一次見)。TMultiReadExclusiveWriteSynchronizer和TCriticalSection不同的是,它允許多個線程同時讀一個變數,只是在寫一個變數時才需要事先阻塞,因為只有多個線程同時寫一個變數才有可能造成衝突。
使用TMREWS的優勢是它允許多線程的並發讀取,同時又與CriticalSection一樣允許讀的時候只有一個線程訪問。劣勢是TMREWS用起來要費更高的代價。
1、聲明一個全域的TMultiReadExclusiveWriteSynchronizer類的執行個體。
2、建立TMultiReadExclusiveWriteSynchronizer.Create。
3、每個線程在讀一個全域變數前要先調用該類的BeginRead()來檢查是否有其他線程在寫這個變數。如果有,就等待,直到其他線程不再寫這個變數才返回。當讀好後,調用EndRead()來結束。
  如果一個線程要寫這個變數,必須先調用BeginWrite()來檢查當前是否有其他現成在寫這個變數並且所有線程是否都調用了EndRead()。只要有一個線程正在寫這個變數,或者有一個線程還沒有調用EndRead(),BeginWrite()將一直等待。當線程寫完以後,必須及時地調用EndWrite(),一邊其他線程可以讀寫這個全域變數。
4、在恰當的位置進行Free,一般在程式的onDestroy裡。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.