2010-07-31 10 views
28

लेख "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 ने दिखाया कि टीएमओनिटर 'निष्पक्ष' है, लेकिन इसका प्रदर्शन एक महत्वपूर्ण खंड से भी बदतर है।

+0

'TMonitor' गंभीर कीड़े, जो अंत में XE2 upd 4 में सही किया गया त्रुटियों' TThreadedQueue' में TMonitor उपयोग द्वारा प्रकट जा सकता था। अधिक जानकारी के लिए ['TThreadedQueue एकाधिक उपभोक्ताओं के लिए सक्षम नहीं है? '] (Http://stackoverflow.com/q/4856306/576719) देखें। –

उत्तर

4

टीएमओनिटर एक शर्त चर के साथ एक महत्वपूर्ण खंड (या एक साधारण म्यूटेक्स) की धारणा को जोड़ता है। आप यहां "मॉनीटर" के बारे में पढ़ सकते हैं: http://en.wikipedia.org/wiki/Monitor_%28synchronization%29

कहीं भी आप एक महत्वपूर्ण अनुभाग का उपयोग करेंगे, आप एक मॉनीटर का उपयोग कर सकते हैं। एक TCriticalSection घोषित करने के बजाय, आप एक टॉब्जेक्ट उदाहरण सरल बना सकते हैं और फिर इसका उपयोग कर सकते हैं।

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

जहां फ़्लॉक कोई ऑब्जेक्ट उदाहरण है। आम तौर पर, मैं सिर्फ एक TObject बनाएँ:

FLock := TObject.Create; 
+0

तो इस उदाहरण में यह 'फ्लॉक' मॉनीटर है? (विकिपीडिया में वर्णित अनुसार "ऑब्जेक्ट को एक से अधिक धागे से सुरक्षित रूप से उपयोग किया जाना चाहिए" – mjn

+0

फ़्लॉक कोई ऑब्जेक्ट उदाहरण है। यह सिर्फ एक साधारण टॉब्जेक्ट उदाहरण हो सकता है। झुंड: = tobject.Create; –

+5

अभी भी पर्याप्त नहीं है। आपने दिखाया है कि टीएमओनिटर के साथ एक महत्वपूर्ण खंड का अनुकरण कैसे करें, लेकिन यह सुनिश्चित करें कि टीएमओनिटर के लिए वास्तविक समस्या नहीं है। क्या आप एक और दिलचस्प कोड उदाहरण दे सकते हैं? – kludg