看完文章
"Simmering Unicode, bring DPL to a boil"
和
"Simmering Unicode, bring DPL to a boil (Part 2)"
在《德尔福的先知》(艾伦·鲍尔)一书中,我所理解的只有先知:)
mutual exclusion locks
和
condition variables
(这篇维基百科文章转发给'
Monitor (synchronization)
,然后介绍新的
TMonitor record type
并介绍了它的一些方法。
是否有介绍文章和例子来说明何时以及如何使用这种Delphi记录类型?有一些
documentation
在线。
-
TCriticalSection和TMonitor的主要区别是什么?
-
我能拿这个做什么
Pulse
PulseAll
方法?
-
-
RTL或VCL中是否有使用此类型的代码(因此可以作为示例)?
更新:文章
Why Has the Size of TObject Doubled In Delphi 2009?
Intrinsic Locks in the Java language
每个对象都有一个内在锁
一致访问对象的
字段必须获取对象的
在访问它们之前,
然后释放内在锁
Wait
Pulse
和
PulseAll
wait()
,
notify()
和
notifyAll()
更新2:
生产者/消费者应用程序的示例代码
使用
TMonitor.Wait
和
TMonitor.PulseAll
Java(tm) tutorials
(欢迎评论):
它创建了数据
消费者,这是有意义的。
共享对象。协调是
不尝试检索数据
交付了,还有制作人线程
不得尝试传递新数据
如果消费者还没有取回
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和Take方法中使用它
TMonitor.Enter(FLock);
.
InterruptedException
在Delphi中可以用来取消
Sleep
.
更新3
:2011年5月
blog entry
Quality Central
. 注释中提到了一个由Delphi用户提供的修补程序,但它不可见。
更新4
blog post
2013年的研究表明,尽管TMonitor是“公平的”,但它的性能比关键部分差。