Delphi系统中TMonitor是什么? [英] What is TMonitor in Delphi System unit good for?
问题描述
阅读文章后,炖炖Unicode,让DPL沸腾和Simmering Unicode,使DPL沸腾(第2部分)
After reading the articles "Simmering Unicode, bring DPL to a boil" and "Simmering Unicode, bring DPL to a boil (Part 2)" of "The Oracle at Delphi" (Allen Bauer), Oracle is all I understand :)
文章提到Delphi并行库(DPL),锁定自由数据结构,互斥锁和条件变量(本维基百科文章转发给监视(同步),然后介绍新的 TMonitor记录类型< a>用于线程同步并进行描述我的方法。
The article mentions Delphi Parallel Library (DPL), lock free data structures, mutual exclusion locks and condition variables (this Wikipedia article forwards to 'Monitor (synchronization)', and then introduces the new TMonitor record type for thread synchronization and describes some of its methods.
是否有介绍文章与示例显示何时以及如何使用这种Delphi记录类型?在线有一些文档。
Are there introduction articles with examples which show when and how this Delphi record type can be used? There is some documentation online.
-
TCriticalSection和TMonitor之间的主要区别是什么?
What is the main difference between TCriticalSection and TMonitor?
我可以使用 Pulse
和 PulseAll
方法?
是否有在C#或Java语言中的一个例子?
Does it have a counterpart for example in C# or the Java language?
RTL或VCL中是否存在使用此类型的代码(因此可以作为例如)
Is there any code in the RTL or the VCL which uses this type (so it could serve as an example)?
更新:文章为什么TObject的大小在Delphi 2009中翻倍?解释说,Delphi中的每个对象现在都可以使用TMonitor记录锁定,每个实例的价格为四个额外的字节。
Update: the article Why Has the Size of TObject Doubled In Delphi 2009? explains that every object in Delphi now can be locked using a TMonitor record, at the price of four extra bytes per instance.
看起来TMonitor类似于 Java语言中的固有锁:
It looks like TMonitor is implemented similar to Intrinsic Locks in the Java language:
每个对象都有一个固有锁
与它相关联。按照惯例,一个
线程需要独占和
一致地访问对象的
字段,必须在访问对象的
内部锁之前获取
,然后释放内部锁
,当它们完成时。
Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them.
等待, Pulse 和Delphi中的 PulseAll 似乎是对应的 wait(), notify()和 notifyAll( )的Java编程语言。更正2:生产者/消费者应用程序的示例代码
Wait, Pulse and PulseAll in Delphi seem to be counterparts of wait(), notify() and notifyAll() in the Java programming language. Correct me if I am wrong :)
使用 TMonitor.Wait
和 TMonitor.PulseAll
,根据关于 Java(tm)教程(欢迎评论):
Update 2: Example code for a Producer/Consumer application using TMonitor.Wait
and TMonitor.PulseAll
, based on an article about guarded methods in the Java(tm) tutorials (comments are welcome):
这种应用程序在两个线程之间共享数据
:生产者,
创建数据,
消费者,这与它做了一些事情。
两个线程使用
共享对象进行通信。协调是
基本:消费者线程必须
在生产者线程
发送之前不尝试检索数据
,生产者线程
不得尝试如果消费者没有检索到
旧数据,则会传送新数据
。
This kind of application shares data between two threads: the producer, that creates the data, and the consumer, that does something with it. The two threads communicate using a shared object. Coordination is essential: the consumer thread must not attempt to retrieve the data before the producer thread has delivered it, and the producer thread must not attempt to deliver new data if the consumer hasn't retrieved the old data.
在此示例中,数据是一系列文本消息,它们通过Drop类型的对象共享:
In this example, the data is a series of text messages, which are shared through an object of type 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.
现在这样可以预期,但有一个我可以改进的细节:而不是锁定整个使用 TMonitor.Enter(Self);
删除实例,我可以选择一个细粒度的锁定方法,使用(私人)FLock字段,仅在Put并通过 TMonitor.Enter(FLock);
获取方法。
Now this works as expected, however there is a detail which I could improve: instead of locking the whole Drop instance with TMonitor.Enter(Self);
, I could choose a fine-grained locking approach, with a (private) "FLock" field, using it only in the Put and Take methods by TMonitor.Enter(FLock);
.
如果我将代码与Java版本进行比较,我还注意到Delphi中没有可用于取消 Sleep
的调用的 InterruptedException
。
If I compare the code with the Java version, I also notice that there is no InterruptedException
in Delphi which can be used to cancel a call of Sleep
.
更新3 :2011年5月,一个博客条目在TMonitor实现中提出了一个可能的错误。它似乎与 Quality Central 中的条目有关。评论提到修补程序是由Delphi用户提供的,但不可见。
Update 3: in May 2011, a blog entry about the OmniThreadLibrary presented a possible bug in the TMonitor implementation. It seems to be related to an entry in Quality Central. The comments mention a patch has been provided by a Delphi user, but it is not visible.
更新4 :A blog post 在2013年显示,虽然TMonitor是公平的,其表现比
Update 4: A blog post in 2013 showed that while TMonitor is 'fair', its performance is worse than that of a critical section.
推荐答案
TMonitor将关键部分(或简单互斥体)的概念与条件变量相结合。您可以阅读监视器在这里: http://en.wikipedia。 org / wiki / Monitor_%28synchronization%29 。
TMonitor combines the notion of a critical section (or a simple mutex) along with a condition variable. You can read about what a "monitor" is here: http://en.wikipedia.org/wiki/Monitor_%28synchronization%29.
任何位置,您将使用关键部分,您可以使用监视器。而不是声明一个TCriticalSection,您可以简单地创建一个TObject实例,然后使用它。
Anyplace you would use a critical section, you can use a monitor. Instead of declaring a TCriticalSection, you can simple create a TObject instance and then use that.
TMonitor.Enter(FLock);
try
// protected code
finally
TMonitor.Exit(FLock);
end;
其中,FLock是任何对象实例。通常,我只是创建一个TObject:
Where FLock is any object instance. Normally, I just create a TObject:
FLock := TObject.Create;
这篇关于Delphi系统中TMonitor是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!