लेख "Simmering Unicode, bring DPL to a boil" और "डेल्फी के दैवज्ञ" (एलन Bauer) "Simmering Unicode, bring DPL to a boil (Part 2)" पढ़ने के बाद, ओरेकल सब मैं समझता हूँ :)डेल्फी सिस्टम इकाई में टीएमओनिटर क्या है?
लेख का उल्लेख है डेल्फी समानांतर लाइब्रेरी (डीपीएल), नि: शुल्क डाटा संरचनाओं ताला mutual exclusion locks और condition variables है, फारवर्ड 'Monitor (synchronization)' के लिए (यह विकिपीडिया लेख, और फिर धागा तुल्यकालन के लिए नई TMonitor record type का परिचय और उसके तरीकों के कुछ वर्णन करता है।
जो दिखाने कब और कैसे इस डेल्फी रिकॉर्ड प्रकार इस्तेमाल किया जा सकता उदाहरण के साथ वहाँ परिचय लेख हैं? वहाँ कुछ documentation ऑनलाइन है।
टीक्रिटिकलसेक्शन और टीएमओनिटर के बीच मुख्य अंतर क्या है?
मैं
Pulse
औरPulseAll
विधियों के साथ क्या कर सकता हूं?क्या इसका उदाहरण सी # या जावा भाषा में उदाहरण के लिए समकक्ष है?
क्या आरटीएल या वीसीएल में कोई कोड है जो इस प्रकार का उपयोग करता है (इसलिए यह एक उदाहरण के रूप में काम कर सकता है)?
अद्यतन: लेख Why Has the Size of TObject Doubled In Delphi 2009? बताते हैं कि डेल्फी में हर वस्तु अब उदाहरण के प्रति चार अतिरिक्त बाइट्स की कीमत पर एक TMonitor रिकॉर्ड का उपयोग कर बंद कर दिया जा सकता है।
यह TMonitor की तरह लग रहा 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);
के साथ पूरे ड्रॉप इंस्टेंस को लॉक करने के बजाय, मैं एक (निजी) "फ्लॉक" फ़ील्ड के साथ एक अच्छी तरह से दाग लॉकिंग दृष्टिकोण चुन सकता हूं, इसका उपयोग केवल पुट एंड टेक विधियों में TMonitor.Enter(FLock);
द्वारा किया जा सकता है।
यदि मैं जावा संस्करण के साथ कोड की तुलना करता हूं, तो मुझे यह भी पता चलता है कि डेल्फी में InterruptedException
नहीं है जिसका उपयोग Sleep
पर कॉल रद्द करने के लिए किया जा सकता है।
अद्यतन 3: मई 2011 में, OmniThreadLibrary के बारे में blog entry TMonitor कार्यान्वयन में संभावित बग प्रस्तुत किया। ऐसा लगता है कि Quality Central में एक प्रविष्टि से संबंधित है। टिप्पणियों का उल्लेख है कि डेल्फी उपयोगकर्ता द्वारा एक पैच प्रदान किया गया है, लेकिन यह दिखाई नहीं दे रहा है।
अपडेट 4: 2013 में blog post ने दिखाया कि टीएमओनिटर 'निष्पक्ष' है, लेकिन इसका प्रदर्शन एक महत्वपूर्ण खंड से भी बदतर है।
'TMonitor' गंभीर कीड़े, जो अंत में XE2 upd 4 में सही किया गया त्रुटियों' TThreadedQueue' में TMonitor उपयोग द्वारा प्रकट जा सकता था। अधिक जानकारी के लिए ['TThreadedQueue एकाधिक उपभोक्ताओं के लिए सक्षम नहीं है? '] (Http://stackoverflow.com/q/4856306/576719) देखें। –