gpt4 book ai didi

delphi - Delphi系统单元中的TMonitor有什么用?

转载 作者:行者123 更新时间:2023-12-03 14:33:06 24 4
gpt4 key购买 nike

阅读文章后"Simmering Unicode, bring DPL to a boil""Simmering Unicode, bring DPL to a boil (Part 2)"在《The Oracle at Delphi》(Allen Bauer)中,Oracle 就是我所理解的一切:)

文章提到Delphi并行库(DPL),无锁数据结构,mutual exclusion lockscondition variables (这篇维基百科文章转发到“Monitor (synchronization)”,然后介绍了用于线程同步的新TMonitor record type并描述了它的一些方法。

是否有带有示例的介绍文章,展示何时以及如何使用此 Delphi 记录类型?有一些documentation在线。

  • TCriticalSection 和 TMonitor 之间的主要区别是什么?

  • 我可以使用 PulsePulseAll 方法做什么?

  • 它是否有对应的语言,例如 C# 或 Java 语言?

  • RTL 或 VCL 中是否有使用此类型的代码(因此可以作为示例)?

<小时/>

更新:文章Why Has the Size of TObject Doubled In Delphi 2009?解释说现在 Delphi 中的每个对象都可以使用 TMonitor 记录来锁定,但每个实例需要四个额外字节。

看起来TMonitor的实现类似于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.

Wait , PulsePulseAll在Delphi中似乎是wait()的对应项, notify()notifyAll()在Java编程语言中。如果我错了请纠正我:)

<小时/>

更新 2:使用 TMonitor.WaitTMonitor.PulseAll 的生产者/消费者应用程序的示例代码,基于一篇有关 protected 文章Java(tm) tutorials中的方法(欢迎评论):

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 类型的对象共享:

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); 锁定整个 Drop 实例方法,具有(私有(private))“FLock”字段,仅在 TMonitor.Enter(FLock); 的 Put 和 Take 方法中使用它。

如果我将代码与 Java 版本进行比较,我还注意到 Delphi 中没有可用于取消 Sleep 调用的 InterruptedException p>

更新 3:2011 年 5 月,blog entry关于 OmniThreadLibrary 的文章提出了 TMonitor 实现中可能存在的错误。它似乎与Quality Central中的条目相关。 。评论提到 Delphi 用户已经提供了一个补丁,但它不可见。

更新 4:A blog post 2013 年的结果表明,虽然 TMonitor 是“一般”,但其性能比关键部分差。

最佳答案

TMonitor 将临界区(或简单互斥体)的概念与条件变量结合起来。您可以在这里了解什么是“监视器”:

http://en.wikipedia.org/wiki/Monitor_%28synchronization%29

任何需要使用关键部分的地方,都可以使用监视器。您可以简单地创建一个 TObject 实例,然后使用它,而不是声明 TCriticalSection:

TMonitor.Enter(FLock);
try
// protected code
finally
TMonitor.Exit(FLock);
end;

其中FLock是任何对象实例。通常,我只是创建一个 TObject:

FLock := TObject.Create;

关于delphi - Delphi系统单元中的TMonitor有什么用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3377579/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com