2008-08-13 13 views
63

मुझे यह विश्वास करने के लिए उठाया गया है कि यदि एकाधिक धागे एक चर का उपयोग कर सकते हैं, तो सभी को उस वैरिएबल से पढ़ना और लिखना सिंक्रनाइज़ेशन कोड, जैसे कि "लॉक" कथन द्वारा संरक्षित किया जाना चाहिए, क्योंकि प्रोसेसर दूसरे थ्रेड पर स्विच कर सकता है एक लिखने के माध्यम से आधे रास्ते।सी # एक परमाणु ऑपरेशन में एक चर का उपयोग कर रहा है?

हालांकि, मैं परावर्तक का उपयोग कर System.Web.Security.Membership के माध्यम से देख रही है और इस तरह कोड मिला था:

public static class Membership 
{ 
    private static bool s_Initialized = false; 
    private static object s_lock = new object(); 
    private static MembershipProvider s_Provider; 

    public static MembershipProvider Provider 
    { 
     get 
     { 
      Initialize(); 
      return s_Provider; 
     } 
    } 

    private static void Initialize() 
    { 
     if (s_Initialized) 
      return; 

     lock(s_lock) 
     { 
      if (s_Initialized) 
       return; 

      // Perform initialization... 
      s_Initialized = true; 
     } 
    } 
} 

क्यों s_Initialized क्षेत्र ताला के बाहर पढ़ने के लिए है? क्या एक और धागा एक ही समय में लिखने की कोशिश नहीं कर सका? परमाणु चर के पढ़ और लिख रहे हैं?

+0

आप में से उन लोगों के लिए जो इस पोस्ट को पढ़ रहे हैं * वर्तमान में * मौजूद है, यह थोड़ा उलझन में है। उपरोक्त कोड को लॉक (अंदर और बाहर) के साथ दोबारा जांचने के लिए ** सही ** तरीका प्रदर्शित करने के लिए समायोजित किया गया है। हालांकि, प्रश्न पाठ प्रारंभिक कोड नमूना को संदर्भित करता है जिसमें दूसरी 's_initialized' चेक शामिल नहीं है। संपादन इतिहास को देखे बिना यह थोड़ा उलझन में है। – GEEF

+0

@GEEF भ्रम के लिए खेद है, लेकिन सवाल वर्तमान कोड को संदर्भित करता है, जिसमें 'लॉक' के अंदर दूसरी जांच भी शामिल है। यह दोबारा जांच लॉकिंग के बारे में कोई सवाल नहीं है, यह परमाणु स्मृति पहुंच के बारे में है, और क्या एक बूलियन को उसी समय लिखा जा सकता है जब इसे पढ़ा जा रहा है। –

उत्तर

35

निश्चित उत्तर के लिए spec पर जाएं। :)

विभाजन I, सीएलआई स्पेक की धारा 12.6.6 कहता है: "एक अनुरूप सीएलआई गारंटी देगा कि सही ढंग से गठबंधन मेमोरी स्थानों तक पहुंच को पढ़ने और लिखने के लिए मूल शब्द आकार पर कोई बड़ा नहीं है जब सभी लेखन तक पहुंच होती है एक स्थान एक ही आकार के हैं। "

तो यह पुष्टि करता है कि s_Initialized कभी अस्थिर नहीं होगा, और 32 बिट्स से छोटे प्राइमेटिव प्रकारों को पढ़ने और लिखने परमाणु हैं।

विशेष रूप से, double और long (Int64 और UInt64) नहीं एक 32-बिट प्लेटफॉर्म पर परमाणु होने की गारंटी नहीं है। आप इन्हें बचाने के लिए Interlocked कक्षा पर विधियों का उपयोग कर सकते हैं।

इसके अतिरिक्त, पढ़ते और लिखते समय परमाणु होते हैं, इसके अलावा, घटाव, और वृद्धि और आदिम प्रकारों में कमी के साथ दौड़ की स्थिति होती है, क्योंकि उन्हें पढ़ना, संचालित करना और फिर से लिखा जाना चाहिए। इंटरलाक्ड क्लास आपको CompareExchange और Increment विधियों का उपयोग करके इन्हें सुरक्षित रखने की अनुमति देता है।

इंटरलॉकिंग प्रोसेसर को रीडॉर्डिंग पढ़ने और लिखने से रोकने के लिए मेमोरी बाधा बनाता है। लॉक इस उदाहरण में एकमात्र आवश्यक बाधा बनाता है।

+3

हालांकि स्मृति शब्द का उपयोग करने से मूल शब्द आकार से बड़ा कोई परमाणु नहीं है, प्रश्न में प्रदान किया गया नमूना कोड पढ़ने/लिखने की रीडरिंग के कारण थ्रेड सुरक्षित नहीं है। अधिक जानकारी के लिए मेरा जवाब देखें। –

+0

अच्छी जगह, थॉमस। प्रत्येक व्यक्ति को अपना जवाब पढ़ना सुनिश्चित करना चाहिए। –

+7

सी # 4 spec '5.5 परिवर्तनीय संदर्भों की परमाणुता निम्नलिखित डेटा प्रकारों के पढ़ने और लिखने परमाणु हैं: बूल, चार, बाइट, एसबीईटी, लघु, ushort, uint, int, float, और संदर्भ प्रकार। इसके अलावा, पिछली सूची में अंतर्निहित प्रकार के साथ enum प्रकारों के पढ़ने और लिखने पर भी परमाणु हैं। लंबे, उलझन, डबल, और दशमलव, साथ ही उपयोगकर्ता द्वारा परिभाषित प्रकार सहित अन्य प्रकार के पढ़ और लिखते हैं, परमाणु होने की गारंटी नहीं है। उस उद्देश्य के लिए डिज़ाइन किए गए लाइब्रेरी फ़ंक्शंस के अलावा, परमाणु पढ़ने-संशोधन-लिखने की कोई गारंटी नहीं है, जैसे कि वृद्धि या कमी के मामले में। – abatishchev

0

मैंने सोचा कि वे थे - मैं आपके उदाहरण में लॉक के बिंदु के बारे में निश्चित नहीं हूं जब तक कि आप एक ही समय में s_Provider के लिए कुछ नहीं कर रहे हैं - तब लॉक यह सुनिश्चित करेगा कि ये कॉल एक साथ हो जाएं।

क्या //Perform initialization टिप्पणी कवर s_Provider बना रहा है? उदाहरण के लिए

private static void Initialize() 
{ 
    if (s_Initialized) 
     return; 

    lock(s_lock) 
    { 
     s_Provider = new MembershipProvider (...) 
     s_Initialized = true; 
    } 
} 

अन्यथा स्थिर संपत्ति-अभी भी शून्य वापस लौटने जा रही है।

+0

"कॉन्फ़िगरेशन करें" टिप्पणी सभी कॉन्फ़िगरेशन-रीडिंग, क्लास-इंस्टेंटियेटिंग और सेटिंग-सेटिंग के लिए खड़ी है जो सदस्यता s_Provider को प्रारंभ करने के लिए करती है, इसलिए मैं समझता हूं कि यह "लॉक" में क्यों है - ताकि यह केवल एक बार किया जा सके। –

2

प्रारंभिक कार्य दोषपूर्ण है। यह संभव है initialisation कोड दो बार निष्पादित किया जाएगा ताला अंदर दूसरी जांच के बिना

private static void Initialize() 
{ 
    if(s_initialized) 
     return; 

    lock(s_lock) 
    { 
     if(s_Initialized) 
      return; 
     s_Initialized = true; 
    } 
} 

: यह इस तरह से अधिक ध्यान देना चाहिए। तो पहला चेक आपको लॉक को अनावश्यक रूप से लॉक करने के लिए प्रदर्शन के लिए है, और दूसरा चेक उस मामले के लिए है जहां थ्रेड प्रारंभिक कोड को निष्पादित कर रहा है लेकिन अभी तक s_Initialized ध्वज सेट नहीं किया है और इसलिए दूसरा थ्रेड पहले चेक पास करेगा और ताला पर इंतजार कर रहे हैं।

+0

यह बेहतर नहीं है, आप लॉक के बाहर कथन को भी हटा सकते हैं। इसके अलावा, यदि केवल एक चीज जो यहां की जाती है, तो मूल "गैर-सुरक्षित" शब्द को सत्य में प्रारंभ करना है। काफी अच्छा था। सबसे बुरी स्थिति में आप इसे दो बार सेट करते हैं, प्रारंभिक वापसी का एकमात्र कारण प्रदर्शन (शुद्धता नहीं) है। – Wedge

+1

मैंने कहा था कि पहली जांच प्रदर्शन के लिए है। ताले बहुत महंगा हैं इसलिए यह हमेशा करने लायक है। दूसरे बिंदु पर, मुझे लगता है कि यह मानना ​​उचित है कि अधिक जटिल कोड छोड़ा गया है। मुझे किसी भी तरह संदेह है कि एमएस अनावश्यक रूप से लॉक की कीमत पर जाएगा। –

+0

आप सही हैं। वास्तविक सदस्यता वर्ग में दूसरी जांच है। मैंने इसे छोड़ दिया क्योंकि मुझे वास्तव में दिलचस्पी है कि क्या लॉक के बाहर, s_Initialized के लिए पहला कॉल थ्रेड-सुरक्षित है। –

0

आप जो पूछ रहे हैं वह यह है कि एक विधि में एक क्षेत्र में कई बार परमाणु - जिसमें उत्तर नहीं है।

उपर्युक्त उदाहरण में, आरंभिक दिनचर्या दोषपूर्ण है क्योंकि इसके परिणामस्वरूप कई प्रारंभिकरण हो सकते हैं। आपको दौड़ की स्थिति को रोकने के लिए s_Initialized लॉक के अंदर और साथ ही ध्वज की जांच करने की आवश्यकता होगी, जिसमें कई थ्रेड s_Initialized ध्वज पढ़ते हैं, उनमें से कोई वास्तव में प्रारंभिक कोड करता है। उदा।,

private static void Initialize() 
{ 
    if (s_Initialized) 
     return; 

    lock(s_lock) 
    { 
     if (s_Initialized) 
      return; 
     s_Provider = new MembershipProvider (...) 
     s_Initialized = true; 
    } 
} 
0

शायद Interlocked एक सुराग देता है। और अन्यथा this one मैं बहुत अच्छा हूं।

मैंने अनुमान लगाया होगा कि उनका परमाणु नहीं है।

1

मुझे लगता है कि आप पूछ रहे हैं कि s_Initialized लॉक के बाहर पढ़ने के दौरान एक अस्थिर स्थिति में हो सकता है। संक्षिप्त जवाब नहीं है। एक साधारण असाइनमेंट/रीड एक असेंबली निर्देश को उबाल देगा जो हर प्रोसेसर पर परमाणु है जिसे मैं सोच सकता हूं।

मुझे यकीन नहीं है कि मामला 64 बिट चर के लिए असाइनमेंट के लिए क्या है, यह प्रोसेसर पर निर्भर करता है, मुझे लगता है कि यह परमाणु नहीं है लेकिन यह शायद आधुनिक 32 बिट प्रोसेसर पर है और निश्चित रूप से सभी 64 बिट प्रोसेसर पर है । जटिल मूल्य प्रकारों का असाइनमेंट परमाणु नहीं होगा।

1

चर के पढ़ने और लिखने परमाणु नहीं हैं। आपको परमाणु पढ़ने/लिखने के अनुकरण के लिए सिंक्रनाइज़ेशन API का उपयोग करने की आवश्यकता है।

इस पर एक भयानक संदर्भ के लिए और समेकन के साथ कई और मुद्दों के लिए, सुनिश्चित करें कि आप जो डफी के latest spectacle की प्रतिलिपि लें। यह एक रिपर है!

1

"सी # एक परमाणु ऑपरेशन में एक चर का उपयोग कर रहा है?"

नहीं। और यह सी # चीज नहीं है, न ही यह एक नेट चीज भी है, यह एक प्रोसेसर चीज है।

ओजे उस स्थान पर है जो जो डफी इस तरह की जानकारी के लिए जाने वाला व्यक्ति है। अगर आप और जानना चाहते हैं तो एएनडी "इंटरलाक्ड" उपयोग करने के लिए एक बेहतरीन खोज शब्द है।

"टूटा हुआ पढ़ता है" किसी भी मूल्य पर हो सकता है जिसका फ़ील्ड एक सूचक के आकार से अधिक तक जोड़ता है।

-1

एक, कभी नहीं ... जैसा कि इंगित किया गया है, यह वास्तव में गलत है। यह दूसरे थ्रेड को "प्रारंभिक" कोड खंड में प्रवेश करने से नहीं रोकता है। बाह।

आप अस्थिर कीवर्ड के साथ s_Initialized को सजाने और पूरी तरह से लॉक के उपयोग को पूर्ववत कर सकते हैं।

+0

बनाना s_Initialized अस्थिर मदद नहीं करेगा। विशेष रूप से, यह दो CPUs को उसी मान को पढ़ने से रोक नहीं देगा और ऑब्जेक्ट बनाने के लिए गलती से आगे बढ़ रहा है। इसे अस्थिर बनाना, मुद्दों को ठीक करने के लिए * प्रतीत होता है, क्योंकि अस्थिर चर के उपयोग से स्मृति पूरी तरह से स्मृति को क्रमबद्ध कर सकता है, समय-समय पर एक असंगत स्थिति में स्मृति छोड़ सकता है, लेकिन परीक्षणों को प्राप्त करने के लिए पर्याप्त रूप से बग को छुपाता है लेकिन वास्तविक दुनिया के तनाव में विफल रहता है। – doug65536

1

तुम भी अस्थिर कीवर्ड के साथ s_Initialized सजाने और पूरी तरह से लॉक का उपयोग त्याग सकता है।

यह सही नहीं है। पहले थ्रेड को ध्वज सेट करने का मौका मिलने से पहले आपको चेक को पार करने वाले दूसरे थ्रेड की समस्या का सामना करना पड़ेगा जिसके परिणामस्वरूप प्रारंभिक कोड के कई निष्पादन होंगे।

7

सही उत्तर लगता है, "हां, ज्यादातर।"

  1. जॉन जवाब CLI कल्पना संदर्भित कि चर तक पहुँचता है एक 32-बिट प्रोसेसर पर से बड़ा 32 बिट नहीं परमाणु कर रहे हैं इंगित करता है।
  2. सी # कल्पना से आगे पुष्टि, खंड 5.5, Atomicity of variable references:

    पढ़ता है और निम्न डेटा प्रकारों के बारे में लिखते हैं परमाणु: bool, चार, बाइट, sbyte, लघु, ushort, uint, int, नाव , और संदर्भ प्रकार। इसके अलावा, पिछली सूची में अंतर्निहित प्रकार के साथ enum प्रकारों के पढ़ने और लिखने पर भी परमाणु हैं। लंबे, उलझन, डबल, और दशमलव, साथ ही उपयोगकर्ता द्वारा परिभाषित प्रकार सहित अन्य प्रकार के पढ़ और लिखते हैं, परमाणु होने की गारंटी नहीं है।

  3. मेरे उदाहरण में कोड, सदस्यता वर्ग से दूसरे शब्दों में बयान किया गया था के रूप में ASP.NET टीम द्वारा स्वयं लिखा है, तो वह हमेशा था ग्रहण करने के लिए जिस तरह से यह तक पहुँचता है कि s_Initialized क्षेत्र सही है सुरक्षित। अब हम जानते हैं क्यों।

संपादित करें: थॉमस Danecker बताते हैं के रूप में, भले ही क्षेत्र की पहुँच परमाणु है, s_Initialized वास्तव में चिह्नित किया जाना चाहिए अस्थिर पुन: क्रम पढ़ता है कि ताला प्रोसेसर द्वारा टूटी नहीं है सुनिश्चित करने के लिए और लिखते हैं।

+0

यह सही नहीं है। कारण के लिए मेरा उत्तर देखें। –

+0

मैं आपका बिंदु देखता हूं, लेकिन मेरे उदाहरण में कोड वास्तविक सदस्यता वर्ग में लॉकिंग के संबंध में सटीक है। शायद एएसपी.नेट टीम अपने कंपाइलर और उनके लक्षित प्रोसेसर के बारे में पर्याप्त जानकारी के बारे में जानती है कि कोई पुनरावृत्ति नहीं होगी। सभी एक ही ... –

+0

... मैं जो लेख से जुड़ा हुआ लेख में जो डफी से सहमत हूं, जब वह कहता है कि हमें हमेशा इस तरह की परिस्थितियों में "अस्थिर" का उपयोग सुरक्षित पक्ष पर होना चाहिए। –

11

इस बारे में लटका - शीर्षक में मौजूद सवाल निश्चित रूप से असली प्रश्न नहीं है जो रोरी पूछ रहा है।

शीर्षक संबंधी प्रश्न का "नो" का सरल उत्तर है - लेकिन जब आप असली सवाल देखते हैं तो यह कोई मदद नहीं है - जो मुझे नहीं लगता कि किसी ने भी एक सरल जवाब दिया है।

असली प्रश्न रोरी पूछताछ बहुत बाद में प्रस्तुत किया जाता है और वह जो उदाहरण देता है उससे अधिक प्रासंगिक है।

s_Initialized फ़ील्ड लॉक के बाहर क्यों पढ़ता है?

इसका उत्तर भी सरल है, हालांकि परिवर्तनीय पहुंच की परमाणुता से पूरी तरह से असंबंधित है।

s_Initialized फ़ील्ड लॉक के बाहर पढ़ा जाता है क्योंकि ताले महंगे हैं।

चूंकि s_Initialized फ़ील्ड अनिवार्य रूप से "एक बार लिखना" है, यह कभी भी झूठी सकारात्मक नहीं लौटाएगा।

लॉक के बाहर इसे पढ़ने के लिए यह आर्थिक है।

यह एक उच्च एक लाभ होने की संभावना के साथ एक कम लागत गतिविधि है।

यही कारण है कि यह लॉक के बाहर पढ़ा जाता है - जब तक यह संकेत नहीं दिया जाता है तब तक लॉक का उपयोग करने की लागत का भुगतान करने से बचें।

यदि ताले सस्ते थे तो कोड आसान होगा, और पहले चेक को छोड़ दें।

(संपादित करें:। रोरी से अच्छा प्रतिक्रिया इस प्रकार है ये, बूलियन पढ़ता बहुत ज्यादा परमाणु कर रहे हैं किसी के साथ गैर-परमाणु बूलियन पढ़ता है, वे DailyWTF पर विशेष रुप से होगी एक प्रोसेसर बनाया है।।)

1


@Leon मैं अपनी बात देखते हैं - जिस तरह से मैंने पूछा है, और फिर पर टिप्पणी की, सवाल यह अलग अलग तरीकों की एक जोड़ी के रूप में लिया जा सकता है।

स्पष्ट होने के लिए, मैं जानना चाहता था कि समवर्ती थ्रेड पढ़ने के लिए सुरक्षित है और बिना किसी स्पष्ट सिंक्रनाइज़ेशन कोड के बूलियन फ़ील्ड को लिखना सुरक्षित है, यानी, एक बूलियन (या अन्य आदिम-टाइप किए गए) चरम परमाणु तक पहुंच रहा है।

मैंने फिर एक ठोस उदाहरण देने के लिए सदस्यता कोड का उपयोग किया, लेकिन इससे डबल-चेक लॉकिंग की तरह विकृतियों का एक गुच्छा पेश किया गया, तथ्य यह है कि s_Initialized केवल एक बार सेट है, और मैंने प्रारंभिक कोड को स्वयं ही टिप्पणी की ।

मेरा बुरा।

34

यह डबल चेक लॉकिंग पैटर्न का एक (खराब) रूप है जो सी # में सुरक्षित थ्रेड नहीं है!

s_Initialized अस्थिर नहीं है:

इस कोड में एक बड़ी समस्या नहीं है। इसका मतलब यह है कि शुरुआती कोड में लिखने के बाद एस_इनिलाइज्ड सत्य पर सेट हो सकता है और अन्य धागे अनियमित कोड देख सकते हैं भले ही s_Initialized उनके लिए सच है। यह फ्रेमवर्क के माइक्रोसॉफ्ट के कार्यान्वयन पर लागू नहीं होता है क्योंकि प्रत्येक लेखन एक अस्थिर लेखन है।

लेकिन माइक्रोसॉफ्ट के कार्यान्वयन में, अनियंत्रित डेटा को पढ़ा जा सकता है (यानी सीपीयू द्वारा प्रीफेच किया गया), इसलिए यदि s_Initialized सत्य है, तो डेटा को प्रारंभ करना चाहिए जिसे कैश की वजह से पुराना, प्रारंभिक डेटा पढ़ना पड़ सकता है -hits (यानी पढ़ा जाता है)।

उदाहरण के लिए: कोई अस्थिर पढ़ा है, क्योंकि कहीं भी

Thread 1 reads s_Provider (which is null) 
Thread 2 initializes the data 
Thread 2 sets s\_Initialized to true 
Thread 1 reads s\_Initialized (which is true now) 
Thread 1 uses the previously read Provider and gets a NullReferenceException 

s_Initialized के पढ़ने से पहले s_Provider के पढ़ने के बढ़ते पूरी तरह से कानूनी है।

यदि s_Initialized अस्थिर होगा, s_Provider के पढ़ने को s_Initialized के पढ़ने से पहले स्थानांतरित करने की अनुमति नहीं दी जाएगी और प्रदाता के प्रारंभिककरण को s_Initialized के बाद स्थानांतरित करने की अनुमति नहीं है और सब कुछ ठीक है।

जो डफी भी इस समस्या के बारे में एक लेख लिखा था: Broken variants on double-checked locking

+0

अच्छा बिंदु। आपके द्वारा लिंक किए गए आलेख को पढ़ना, चाहे सदस्यता में कोड सही या गलत है, संकलक और प्रोसेसर के सटीक विवरण पर निर्भर करता है, लेकिन मैं सहमत हूं कि s_Initialized को सुनिश्चित करने के लिए अस्थिर बनाया जाना चाहिए। –

+0

यह * नेट की मेमोरी मॉडेल के अनुसार गलत है। कुछ प्रोसेसर और/या कुछ कंपाइलरों के साथ, आप भाग्यशाली विचार कर सकते हैं कि यह अभी भी काम करता है। जो डफी ने एक और लेख लिखा: http://www.bluebytesoftware.com/blog/2008/07/17/LoadsCannotPassOtherLoadsIsAMyth.aspx –

+0

लेखन पुनर्वितरण की अनुपस्थिति x86 और x64 की विशेषता है, लेकिन माइक्रोसॉफ्ट के .NET, यानी मैं आवश्यक नहीं हूं। यदि माइक्रोसॉफ्ट अन्य आर्किटेक्चर के लिए समर्थन जोड़ता है तो हार्डवेयर उस पर भरोसा नहीं करेगा जहां हार्डवेयर रीडर लिखता है। –

0

बनाने के अपने कोड हमेशा कमजोर आदेश दिया आर्किटेक्चर पर काम करते हैं, आप एक MemoryBarrier इससे पहले कि आप s_Initialized बारे में डाल दिया जाना चाहिए।

s_Provider = new MemershipProvider; 

// MUST PUT BARRIER HERE to make sure the memory writes from the assignment 
// and the constructor have been wriitten to memory 
// BEFORE the write to s_Initialized! 
Thread.MemoryBarrier(); 

// Now that we've guaranteed that the writes above 
// will be globally first, set the flag 
s_Initialized = true; 

स्मृति लिखते हैं कि MembershipProvider निर्माता में होती हैं और s_Provider को लिखने से पहले आप एक कमजोर आदेश दिया प्रोसेसर पर s_Initialized को लिखने होने की गारंटी नहीं है।

इस धागे में बहुत से विचार इस बारे में है कि कुछ परमाणु है या नहीं। समस्या यह नहीं है। मुद्दा ऑर्डर है कि आपके धागे के लेखन अन्य धागे पर दिखाई दे रहे हैं। कमजोर आदेशित आर्किटेक्चर पर, स्मृति में लिखते हैं क्रम में नहीं होते हैं और यह वास्तविक मुद्दा है, न कि एक चर डेटा डेटा के भीतर फिट बैठता है या नहीं।

संपादित करें: वास्तव में, मैं अपने बयान में प्लेटफॉर्म मिश्रण कर रहा हूं।सी # सीएलआर स्पेक में यह आवश्यक है कि लिखने वैश्विक रूप से दिखाई दे, इन-ऑर्डर (यदि आवश्यक हो तो प्रत्येक स्टोर के लिए महंगे स्टोर निर्देशों का उपयोग करके)। इसलिए, आपको वास्तव में उस स्मृति बाधा को रखने की आवश्यकता नहीं है। हालांकि, अगर यह सी या सी ++ था, जहां वैश्विक दृश्यता आदेश की ऐसी कोई गारंटी मौजूद नहीं है, और आपके लक्षित प्लेटफॉर्म ने कमजोर आदेश दिया है, और यह बहुप्रचारित है, तो आपको यह सुनिश्चित करने की आवश्यकता होगी कि रचनाकार लिखने से पहले वैश्विक रूप से दिखाई दे रहे हैं s_Initialized , जो ताला के बाहर परीक्षण किया जाता है।

0

एक If (itisso) { एक बूलियन पर जांच परमाणु है, लेकिन अगर यह नहीं था तो पहले चेक को लॉक करने की कोई आवश्यकता नहीं है।

यदि किसी भी धागे ने प्रारंभिकरण पूरा कर लिया है तो यह सच होगा। इससे कोई फर्क नहीं पड़ता कि कई धागे एक बार में जांच कर रहे हैं। वे सभी एक ही जवाब प्राप्त करेंगे, और, कोई संघर्ष नहीं होगा।

लॉक के अंदर दूसरी जांच आवश्यक है क्योंकि एक और धागे ने पहले लॉक पकड़ लिया हो और प्रारंभिक प्रक्रिया को पहले ही पूरा कर लिया हो।

संबंधित मुद्दे