• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Delphi多线程编程之五不同类线程读写全局变量-阻塞和锁定

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

(调试环境: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里。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Matlab学习——求解微分方程(组)发布时间:2022-07-18
下一篇:
Java中使用MATLAB作图发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap