2008-09-03 12 views
14

मैं एक सी # सिंगलटन वर्ग है कि कई वर्गों का उपयोग करें। Instance के माध्यम से Toggle() विधि थ्रेड-सुरक्षित तक पहुंच है? यदि हां, तो क्या द्वारा मान्यताओं, नियम, आदि यदि नहीं, तो क्यों और मैं इसे कैसे ठीक कर सकते हैं?थ्रेड-सुरक्षित एक सिंगलटन के सदस्यों के प्रयोग के

public class MyClass 
{ 
    private static readonly MyClass instance = new MyClass(); 

    public static MyClass Instance 
    { 
     get { return instance; } 
    } 

    private int value = 0; 

    public int Toggle() 
    { 
     if(value == 0) 
     { 
      value = 1; 
     } 
     else if(value == 1) 
     { 
      value = 0; 
     } 

     return value; 
    } 
} 
+0

क्या इसे वास्तव में सिंगलटन होने के लिए निजी सीटीओ की आवश्यकता है? –

उत्तर

26

'टॉगल()' कक्षा थ्रेडसेफ में 'इंस्टेंस' के माध्यम से पहुंच है? यदि हां, किस धारणाओं, नियमों, आदि से। यदि नहीं, तो मैं इसे कैसे और कैसे ठीक कर सकता हूं?

नहीं, यह threadsafe नहीं है।

असल में, दोनों धागे एक ही समय में Toggle समारोह चला सकते हैं, तो यह

// thread 1 is running this code 
    if(value == 0) 
    { 
     value = 1; 
     // RIGHT NOW, thread 2 steps in. 
     // It sees value as 1, so runs the other branch, and changes it to 0 
     // This causes your method to return 0 even though you actually want 1 
    } 
    else if(value == 1) 
    { 
     value = 0; 
    } 
    return value; 

आप नीचे दिए गए इस धारणा के साथ काम करने की जरूरत है हो सकता है।

यदि 2 धागे चल रहे हैं, तो वे किसी भी बिंदु पर यादृच्छिक रूप से एक दूसरे के साथ बातचीत कर सकते हैं और बातचीत कर सकते हैं। आप 64 बिट पूर्णांक या फ्लोट (32 बिट सीपीयू पर) लिखने या पढ़ने के माध्यम से आधा रास्ता हो सकते हैं और दूसरा धागा कूद सकता है और इसे नीचे से बदल सकता है।

यदि 2 धागे कभी भी सामान्य में कुछ भी नहीं पहुंचते हैं, तो इससे कोई फर्क नहीं पड़ता, लेकिन जैसे ही वे करते हैं, आपको उन्हें एक दूसरे के पैर की उंगलियों पर कदम उठाने से रोकने की आवश्यकता होती है। .NET में ऐसा करने का तरीका ताले के साथ है।

आप क्या और कहाँ इस तरह चीजों के बारे में सोच को लॉक करते हैं तय कर सकते हैं:

कोड का एक दिए गए ब्लॉक के लिए, यदि something का मूल्य मुझे नीचे से बाहर बदल गया, इससे कोई फर्क होगा? यदि ऐसा होगा, तो आपको उस कोड की अवधि के लिए उस something को लॉक करने की आवश्यकता होगी जहां यह महत्वपूर्ण होगा।

अपने उदाहरण को देखते फिर

// we read value here 
    if(value == 0) 
    { 
     value = 1; 
    } 
    else if(value == 1) 
    { 
     value = 0; 
    } 
    // and we return it here 
    return value; 

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

lock(value) 
{ 
    if(value == 0) 
    ... // all your code here 
    return value; 
} 

हालांकि

:

तो आप ऐसा करते हैं चाहते हैं। Int32 एक वैल्यू टाइप है, इसलिए हम इसे लॉक नहीं कर सकते हैं।
हम इसे 'डमी' ऑब्जेक्ट पेश करके और लॉक करते हुए लॉक करते हैं, जहां भी हम 'मान' लॉक करना चाहते हैं।

यह Ben Scheirman का जिक्र है।

+0

कुशल! बहुत उपयोगी, धन्यवाद। –

+0

मेरी इच्छा है कि मैंने थ्रेड और थ्रेड सुरक्षा की अवधारणाओं को सीखते समय शुरुआत में इसे वापस पढ़ा था। –

0

उद्धरण:

if(value == 0) { value = 1; } 
if(value == 1) { value = 0; } 
return value; 

value हमेशा 0 हो जाएगा ...

2

आपका धागा एक अलग धागा है कि विधि और हस्तांतरण नियंत्रण के बीच में रोक सकता है। आपको लगता है कि कोड के चारों ओर एक महत्वपूर्ण अनुभाग ...

private static object _lockDummy = new object(); 


... 

lock(_lockDummy) 
{ 
    //do stuff 
} 
+0

लेकिन के बजाय (_lockDummy()) का मतलब है कि आप लॉक (_lockDummy) –

+0

धन्यवाद, अब यह तय हो गया है। –

+0

नहीं, यह तय नहीं है। यह अभी भी '_lockDummy' का उपयोग कर पढ़ता है 'इसे' लॉक (_lockDummy) ' – AndrewJacksonZA

0

खैर की जरूरत है, मैं वास्तव में सी # कि अच्छी तरह से पता नहीं है ... लेकिन मैं जावा में ठीक हूँ, तो मैं उस के लिए इस सवाल का जवाब दे देंगे, और उम्मीद है कि दोनों इतने समान हैं कि यह उपयोगी होगा। यदि नहीं, तो मैं क्षमा चाहता हूं।

जवाब है, नहीं, यह सुरक्षित नहीं है। एक थ्रेड अन्य के रूप में एक ही समय में टॉगल() कह सकते हैं, और यह इस कोड के साथ हालांकि संभावना नहीं संभव है,, Thread1 बार के बीच में value सेट कर सकते हैं कि कि Thread2 यह जाँच करता है और जब यह तय करता है।

ठीक करने के लिए, बस टॉगल() synchronized बनाते हैं। यह किसी भी चीज़ पर अवरुद्ध नहीं होता है या किसी भी थ्रेड को कॉल नहीं करता है जो टॉगल() को कॉल कर सकता है, इसलिए आपको इसे सहेजना है।

7

मूल impplementation सुरक्षित थ्रेड नहीं है, के रूप में बेन इसे सुरक्षित धागा बनाने के लिए एक आसान तरीका बाहर

बताते हैं एक ताला बयान पेश करने का है। उदाहरण के लिए। इस तरह:

public class MyClass 
{ 
    private Object thisLock = new Object(); 
    private static readonly MyClass instance = new MyClass(); 
    public static MyClass Instance 
    { 
     get { return instance; } 
    } 
    private Int32 value = 0; 
    public Int32 Toggle() 
    { 
     lock(thisLock) 
     { 
      if(value == 0) 
      { 
       value = 1; 
      } 
      else if(value == 1) 
      { 
       value = 0; 
      } 
      return value; 
     } 
    } 
} 
1

मैं भी एक संरक्षित निर्माता MyClass के लिए एक सार्वजनिक डिफ़ॉल्ट निर्माता पैदा करने से रोकने के लिए संकलक जोड़ना होगा।

3

यही मैंने सोचा था। लेकिन, मुझे लगता है मैं जानकारी के लिए देख रहा हूँ ... 'टॉगल()' नहीं एक स्थिर विधि (जब 'उदाहरण' का प्रयोग करके) है, लेकिन यह एक स्थिर संपत्ति का एक सदस्य है। क्या यह बनाता है जो इसे धागे के बीच साझा करता है?

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

और यह आम तौर पर सिंगलटन पर कैसे लागू होता है। क्या मुझे अपनी कक्षा में हर विधि में पता करना होगा?

जैसा कि मैंने ऊपर कहा था, क्योंकि यह एक सिंगलटन आपको पता है कि अलग-अलग धागे एक ही वस्तु को एक ही समय में एक ही वस्तु को स्वीकार करेंगे। इसका मतलब यह नहीं है कि आपको हर विधि को लॉक प्राप्त करना है। अगर आपको लगता है कि एक simultaneos मंगलाचरण वर्ग के भ्रष्ट राज्य को जन्म दे सकता नोटिस, तो आप विधि @Thomas

ने उल्लेख आवेदन करना चाहिए
2

मैं मान सकते हैं कि सिंगलटन पैटर्न सब करने के लिए अपने अन्यथा सुंदर धागे की सुरक्षित वर्ग को उजागर करता है नियमित स्थिर सदस्यों की धागे की समस्याएं?

नहीं। आपकी कक्षा बस थ्रेडसेफ नहीं है। सिंगलटन के पास इसके साथ कुछ लेना देना नहीं है।

यह या तो उस के साथ कोई लेना देना नहीं है (मैं तथ्य यह है कि एक स्थिर वस्तु कारण सूत्रण समस्याओं पर कहा जाता है उदाहरण के सदस्यों के आसपास मेरे सिर हो रही है)।

आपको ऐसा सोचना होगा: क्या यह मेरे प्रोग्राम में 2 (या अधिक) थ्रेड के लिए एक ही समय में डेटा के इस टुकड़े तक पहुंचने के लिए संभव है?

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

1

मैं सोच रहा था कि अगर मैं सिंगलटन पैटर्न डंप और वर्ग यह कुछ समस्याओं को कम करेगा का एक नया उदाहरण प्राप्त करने के लिए हर किसी के लिए मजबूर ... लेकिन यह है कि इस बात का एक स्थिर वस्तु आरंभ से किसी और को नहीं रुकती टाइप करें और पास करें ... या एकाधिक थ्रेडों को कताई से, सभी एक ही उदाहरण से 'टॉगल()' तक पहुंचते हैं।

बिंगो :-)

मैं अब समझ गया। यह एक कठिन दुनिया है। काश मैं विरासत कोड पुनर्रचना नहीं थे :(

दुर्भाग्य से, बहु सूत्रण कठिन है और आप चीजों को :-) इस मामले में सबसे सरल समाधान सिंगलटन के साथ रहना है के बारे में बहुत पागल हो, और जोड़ने के लिए उदाहरण के समान मूल्य के चारों ओर एक ताला।

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