什么是德尔福系统单元TMonitor有好处?
阅读文章
“Simmering Unicode,bring DPL to a boil”和
“Simmering Unicode,bring DPL to a boil (Part 2)”的“Oracle在Delphi”(艾伦鲍尔),Oracle是我所理解的:)
文章提到Delphi并行库(DPL),无锁数据结构,mutual exclusion locks和condition variables(这篇维基百科文章转发到“Monitor (synchronization)”,然后介绍了新的TMonitor record type线程同步,并描述了它的一些方法。 有没有介绍文章与示例,显示何时和如何这个Delphi记录类型可以使用?有一些documentation在线。 > TCriticalSection和TMonitor之间的主要区别是什么? 更新:文章Why Has the Size of TObject Doubled In Delphi 2009?解释说,现在可以使用TMonitor记录锁定Delphi中的每个对象,每个实例的价格为4个额外字节。 看起来TMonitor的实现类似于Intrinsic Locks in the Java language:
在Delphi中的Wait,Pulse和PulseAll似乎是Java编程语言中的wait(),notify()和notifyAll()的对应物。纠正我,如果我错了:) 更新2:使用TMonitor.Wait和TMonitor.PulseAll的生产者/消费者应用程序的示例代码,基于Java(tm) tutorials中有关保护方法的文章(欢迎提出意见):
在此示例中,数据是一系列文本消息,通过Drop类型的对象共享: program TMonitorTest; // based on example code at http://download.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html {$APPTYPE CONSOLE} uses SysUtils,Classes; type Drop = class(TObject) private // Message sent from producer to consumer. Msg: string; // True if consumer should wait for producer to send message,false // if producer should wait for consumer to retrieve message. Empty: Boolean; public constructor Create; function Take: string; procedure Put(AMessage: string); end; Producer = class(TThread) private FDrop: Drop; public constructor Create(ADrop: Drop); procedure Execute; override; end; Consumer = class(TThread) private FDrop: Drop; public constructor Create(ADrop: Drop); procedure Execute; override; end; { Drop } constructor Drop.Create; begin Empty := True; end; function Drop.Take: string; begin TMonitor.Enter(Self); try // Wait until message is available. while Empty do begin TMonitor.Wait(Self,INFINITE); end; // Toggle status. Empty := True; // Notify producer that status has changed. TMonitor.PulseAll(Self); Result := Msg; finally TMonitor.Exit(Self); end; end; procedure Drop.Put(AMessage: string); begin TMonitor.Enter(Self); try // Wait until message has been retrieved. while not Empty do begin TMonitor.Wait(Self,INFINITE); end; // Toggle status. Empty := False; // Store message. Msg := AMessage; // Notify consumer that status has changed. TMonitor.PulseAll(Self); finally TMonitor.Exit(Self); end; end; { Producer } constructor Producer.Create(ADrop: Drop); begin FDrop := ADrop; inherited Create(False); end; procedure Producer.Execute; var Msgs: array of string; I: Integer; begin SetLength(Msgs,4); Msgs[0] := 'Mares eat oats'; Msgs[1] := 'Does eat oats'; Msgs[2] := 'Little lambs eat ivy'; Msgs[3] := 'A kid will eat ivy too'; for I := 0 to Length(Msgs) - 1 do begin FDrop.Put(Msgs[I]); Sleep(Random(5000)); end; FDrop.Put('DONE'); end; { Consumer } constructor Consumer.Create(ADrop: Drop); begin FDrop := ADrop; inherited Create(False); end; procedure Consumer.Execute; var Msg: string; begin repeat Msg := FDrop.Take; WriteLn('Received: ' + Msg); Sleep(Random(5000)); until Msg = 'DONE'; end; var ADrop: Drop; begin Randomize; ADrop := Drop.Create; Producer.Create(ADrop); Consumer.Create(ADrop); ReadLn; end. 现在这个工作作为预期,但有一个细节,我可以改进:而不是锁定整个Drop实例与TMonitor.Enter(Self);我可以选择一个细粒度锁定方法,与(私人)“FLock”字段,仅在通过TMonitor.Enter(FLock);在Put和Take方法中使用它。 如果我将代码与Java版本进行比较,我还注意到在Delphi中没有InterruptedException可以用来取消Sleep的调用。 更新3:2011年5月,一个关于OmniThreadLibrary的blog entry提出了TMonitor实现中可能的错误。它似乎与一个条目相关在Quality Central.评论提到的补丁是由Delphi用户提供的,但它是不可见的。 更新4:2013年blog post显示,虽然TMonitor是“公平”,其性能比关键部分差。 解决方法
TMonitor将关键部分(或简单互斥体)的概念与条件变量结合在一起。你可以阅读这里的“监视器”:
http://en.wikipedia.org/wiki/Monitor_%28synchronization%29。
任何地方,你会使用一个关键部分,你可以使用监视器。而不是声明一个TCriticalSection,你可以简单地创建一个TObject实例,然后使用它。 TMonitor.Enter(FLock); try // protected code finally TMonitor.Exit(FLock); end; 其中FLock是任何对象实例。通常,我只是创建一个TObject: FLock := TObject.Create; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |