मुझे मेमोरी डेटा स्ट्रक्चर मिला है जो एकाधिक थ्रेड द्वारा पढ़ा जाता है और केवल एक थ्रेड द्वारा लिखा जाता है। वर्तमान में मैं इस एक्सेस थ्रेडसेफ को बनाने के लिए एक महत्वपूर्ण खंड का उपयोग कर रहा हूं। दुर्भाग्यवश इसका पाठकों को अवरुद्ध करने का असर पड़ता है, भले ही केवल एक और पाठक इसे एक्सेस कर रहा हो।लॉक फ्री एकाधिक पाठक एकल लेखक
इस उपाय करने दो विकल्प हैं:
- उपयोग TMultiReadExclusiveWriteSynchronizer
- अब तक निम्नलिखित एक ताला मुक्त दृष्टिकोण
उपयोग करके किसी भी अवरुद्ध से दूर 2. के लिए मैं मिल गया है (कोई भी कोड जो इससे कोई फर्क नहीं पड़ता है):
type
TDataManager = class
private
FAccessCount: integer;
FData: TDataClass;
public
procedure Read(out _Some: integer; out _Data: double);
procedure Write(_Some: integer; _Data: double);
end;
procedure TDataManager.Read(out _Some: integer; out _Data: double);
var
Data: TDAtaClass;
begin
InterlockedIncrement(FAccessCount);
try
// make sure we get both values from the same TDataClass instance
Data := FData;
// read the actual data
_Some := Data.Some;
_Data := Data.Data;
finally
InterlockedDecrement(FAccessCount);
end;
end;
procedure TDataManager.Write(_Some: integer; _Data: double);
var
NewData: TDataClass;
OldData: TDataClass;
ReaderCount: integer;
begin
NewData := TDataClass.Create(_Some, _Data);
InterlockedIncrement(FAccessCount);
OldData := TDataClass(InterlockedExchange(integer(FData), integer(NewData));
// now FData points to the new instance but there might still be
// readers that got the old one before we exchanged it.
ReaderCount := InterlockedDecrement(FAccessCount);
if ReaderCount = 0 then
// no active readers, so we can safely free the old instance
FreeAndNil(OldData)
else begin
/// here is the problem
end;
end;
दुर्भाग्य से इसे बदलने के बाद ओल्डडाटा इंस्टेंस से छुटकारा पाने की छोटी समस्या है। यदि कोई अन्य धागा वर्तमान में रीड विधि (रीडरकाउंट = 0) के भीतर नहीं है, तो इसे सुरक्षित रूप से निपटाया जा सकता है और यही वह है। लेकिन अगर ऐसा नहीं है तो मैं क्या कर सकता हूं? मैं इसे अगली कॉल तक बस स्टोर कर सकता हूं और इसे वहां से निपट सकता हूं, लेकिन विंडोज शेड्यूलिंग सिद्धांत में रीडर विधि के भीतर एक पाठक धागा सो सकती है और अभी भी ओल्डडाटा का संदर्भ मिला है।
यदि आपको उपरोक्त कोड के साथ कोई अन्य समस्या दिखाई देती है, तो कृपया मुझे इसके बारे में बताएं। यह कई कोर वाले कंप्यूटरों पर चलाना है और उपर्युक्त तरीकों को अक्सर बार कहा जाता है।
इस मामले में: मैं बिल्टिन मेमोरी मैनेजर के साथ डेल्फी 2007 का उपयोग कर रहा हूं। मुझे पता है कि स्मृति प्रबंधक शायद एक नई कक्षा बनाते समय कुछ लॉक लागू करता है लेकिन मैं इस पल के लिए इसे अनदेखा करना चाहता हूं।
संपादित करें: यह उपर्युक्त से स्पष्ट नहीं हो सकता है: TDataManager ऑब्जेक्ट के पूर्ण जीवनकाल के लिए डेटा में केवल एक धागा है जो लिखने के लिए प्रतिस्पर्धा कर सकता है। तो यह एमआरडब्ल्यू का एक विशेष मामला है।
मैं स्वयं लिखित लॉक-फ्री कोड से सावधान हूं, इसे सही करने के लिए लगभग असंभव है। टीएमआरडब्ल्यूएस के लिए: सामान्य मशीनों पर आपके उपयोग-मामले के समय के आसपास कोई रास्ता नहीं है, क्योंकि उन्हें लागू करने के विभिन्न तरीके हैं, और वीसीएल आपको केवल एक देता है। विभिन्न कार्यान्वयन (समय सहित) की तुलना में एक लेख के लिए http://www.codeproject.com/KB/threads/testing_rwlocks.aspx – mghie