您现在的位置:首页 >> 基础算法 >> window基础 >> 内容

Delphi中多线程安全和并发问题(3)

时间:2011/9/3 15:36:58 点击:

 var
  GLogCS: TCriticalSection;
  GUserLog: TStringList;
  procedure TformMain.IdTCPServer1Connect(AThread: TIdPeerThread);
  var
  s: string;
  begin
  // Username
  s := ReadLn;
  GLogCS.Enter; try
  GUserLog.Add('User logged in: ' + s);
  finally GLogCS.Leave; end;
  end;
  procedure TformMain.Timer1Timer(Sender: TObject);
  begin
  GLogCS.Enter; try
  listbox1.Items.AddStrings(GUserLog);
  GUserLog.Clear;
  finally GLogCS.Leave; end;
  end;
  initialization
  GLogCS := TCriticalSection.Create;
  GUserLog := TStringList.Create;
  finalization
  FreeAndNil(GUserLog);
  FreeAndNil(GLogCS);
  end.

  在Connect事件中,用户名在进入Critical Section之前被读入一个临时变量。这样做是为了避免由阻塞Critical Section带来的对客户端可能的减慢。这使得网络通信能够在进入Critical Section之前被执行。为了使得性能最佳,Critical Section中的代码应该越少越好。

  Timer1Timer事件在主线程中被主窗体上的一个计时器触发。计时器的时间间隔可以被缩短来达到更新更加频繁的目的,但是可能会降低接受连接的速度。如果日志的功能被扩展到了服务器的其他地方,不仅仅是记录用户的连接,这更加剧了产生瓶颈的可能。更短促的时间的间隔,更新用户界面所需的时间就更少。然而许多服务器根本就没有用户界面,即便是有也一般是第二位的,比服务客户端的优先级低得多,从而这是一个很好接受的权衡。

  TCritical Section位于SyncObjs Unit中。SyncObjs Unit没有包括在Delphi 4的标准版中。如果你正在使用Delphi 4的标准版,在Indy的网站上有一个SyncObjs.pas,它虽然没有实现Borland的SyncObjs.pas中的所有内容,但是实现了TCriticalSection类。

  TMultiReadExclusiveWriteSynchronizer(TMREWS)

  在前面的例子中,TCriticalSection被用来保护对全局数据的访问。在那些情况中,全局数据只是一直被更新。然而,如果全局数据有时被只读的访问,使用TMultiReadExclusiveWriteSynchronizer可能产生更加有效率的源代码。TMultiReadExclusiveWriteSynchronizer是一个冗长而又难读的类。因此它将被简单的称作TMREWS。

  使用TMREWS的优势是它允许多线程的并发读取,同时又与Critical Section一样允许读的时候只有一个线程访问。劣势是TMREWS用起来要费更高的代价。

  不再是Enter/Acquire和Leave/Release,TMREWS有方法BeginRead,EndRead,BeginWrite和EndWrite。

  关于TMREWS的特别说明

  在Delphi 6之前,TMultiReadExclusiveWriteSynchronizer在从一个read lock变为一个write lock时可能导致死锁。因此你绝对不应该使用把read lock变成write lock的特性,即便文档上说是可以这么做的。

  如果你需要使用这个功能,有一个折衷的办法。那就是先释放read lock然后再获得write lock。然而一旦你获得了write lock,然后你必须再次检查首先迫使你要用一个write lock的条件。如果它仍然存在,执行需要做的事情,否则立刻释放write lock。

  在使用Delphi 6时,TMultiReadExclusiveWriteSynchronizer还是有特别要考虑的地方。所有版本的TMultiReadExclusiveWriteSynchronizer,包括update pack 1和update pack 2中的,都有可能导致死锁的严重问题。没有已知的解决办法。Borland知道这个问题的存在,并且已经发布了非官方的补丁并且可能会发布官方的补丁。

上一页12345下一页

作者:网络 来源:转载
共有评论 0相关评论
发表我的评论
  • 大名:
  • 内容:
  • 盒子文章(www.2ccc.com) © 2024 版权所有 All Rights Reserved.
  • 沪ICP备05001939号