जावा के सिंक्रनाइज़ किए गए कीवर्ड का # संस्करण?


313

क्या c # का java "सिंक्रोनाइज़" कीवर्ड का अपना संस्करण है?

यानी जावा में इसे किसी फंक्शन, ऑब्जेक्ट या कोड के ब्लॉक के रूप में निर्दिष्ट किया जा सकता है, जैसे:

public synchronized void doImportantStuff() {
   // dangerous code goes here.
}

या

public void doImportantStuff() {
   // trivial stuff

   synchronized(someLock) {
      // dangerous code goes here.
   }
}

3
ब्लॉक फॉर्म को लॉक करने के लिए एक संदर्भ की आवश्यकता होती है। विधि के रूप में लॉक ऑब्जेक्ट स्पष्ट रूप से यह है (या वर्ग [this.class, getClass नहीं) () स्थिर तरीकों के लिए, लेकिन कक्षाओं पर लॉक न करें)।
टॉम हॉल्टिन -

1
फिर भी संरक्षित नहीं? मैं हमेशा यहां आता हूं क्योंकि मुझे वह [MethodImpl(MethodImplOptions.Synchronized)]लाइन याद नहीं है ।
Bitterblue

1
मुझे लगता है कि आपका दूसरा स्निपेट संकलन नहीं करेगा - इसे कुछ पर सिंक्रनाइज़ करने की आवश्यकता है।
PoweredByRice

जवाबों:


466

पहला - अधिकांश वर्गों को थ्रेड-सुरक्षित होने की आवश्यकता नहीं होगी। YAGNI का उपयोग करें : केवल थ्रेड-सुरक्षा लागू करें जब आप जानते हैं कि आप वास्तव में इसका उपयोग करने जा रहे हैं (और इसका परीक्षण करें)।

विधि-स्तरीय सामग्री के लिए, वहाँ है [MethodImpl]:

[MethodImpl(MethodImplOptions.Synchronized)]
public void SomeMethod() {/* code */}

इसका उपयोग एक्सेसर्स (गुणों और घटनाओं) पर भी किया जा सकता है:

private int i;
public int SomeProperty
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    get { return i; }
    [MethodImpl(MethodImplOptions.Synchronized)]
    set { i = value; }
}

ध्यान दें कि घटनाओं की तरह क्षेत्र रहे हैं , डिफ़ॉल्ट रूप से सिंक्रनाइज़ जबकि ऑटो कार्यान्वित गुण नहीं हैं :

public int SomeProperty {get;set;} // not synchronized
public event EventHandler SomeEvent; // synchronized

व्यक्तिगत रूप से, मैं के कार्यान्वयन पसंद नहीं MethodImplयह ताले के रूप में thisया typeof(Foo)जो सबसे अच्छा अभ्यास के खिलाफ है -। पसंदीदा विकल्प अपने स्वयं के ताले का उपयोग करना है:

private readonly object syncLock = new object();
public void SomeMethod() {
    lock(syncLock) { /* code */ }
}

ध्यान दें कि फ़ील्ड जैसी घटनाओं के लिए, लॉकिंग कार्यान्वयन कंपाइलर पर निर्भर है; पुराने Microsoft संकलक में यह एक lock(this)/ lock(Type)- है, हालांकि, अधिक हाल के संकलक में यहInterlocked अपडेट का उपयोग करता है - इसलिए थ्रेड-सेफ बिना गंदा भागों के।

यह अधिक दानेदार उपयोग की अनुमति देता है, और धागे के बीच संवाद करने के लिए Monitor.Wait/ Monitor.Pulseआदि के उपयोग की अनुमति देता है ।

एक संबंधित ब्लॉग प्रविष्टि (बाद में पुनरीक्षित )।


@earcam और आपका सवाल है? वह कथन सत्य है। बहुसंख्यक वर्गों को थ्रेड-सेफ़ होने की कोई आवश्यकता नहीं है, थ्रेड-सेफ्टी के लिए परीक्षण नहीं किया जाएगा, और थ्रेड-सेफ्टी होने से प्रदर्शन प्रभावित होगा। प्रकार है कि सही मायने में धागे के बारे में चिंता करने की जरूरत की संख्या बहुत छोटा है - जानबूझकर सिंक्रनाइज़ संग्रह, multiplexers, आदि
मार्क Gravell

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

6
मार्क के लिंक किए गए ब्लॉग पोस्ट में एक मार्च 2010 के बाद अनुवर्ती है कि .NET 4.0, MethodImplऔर फ़ील्ड जैसी घटनाओं में अब अच्छा सिंक्रनाइज़ेशन कोड उत्पन्न होता है, और यह अब अपने स्वयं के ताले का उपयोग करने के लिए आवश्यक नहीं है।
रोरी ओ'केन

2
इन दिनों अनुप्रयोगों का एक अच्छा हिस्सा वेब-आधारित है, जो निर्भरता-इंजेक्शन के माध्यम से भारी उदाहरण के पुन: उपयोग और जटिल वस्तु जीवनचक्र पर भरोसा करने वाले चौखटे के साथ परोसा जाता है। इन दिनों डिफ़ॉल्ट मानसिकता थ्रेड-सेफ्टी के पक्ष में आ जाती है।
भेड़ का जनाब

1
@ इज़र को अब बहुत देर हो चुकी है, लेकिन रिकॉर्ड के लिए: यदि आपने इसे .net मानक / .net कोर टेम्प्लेट का उपयोग करके बनाया है तो फ्रेमवर्क को बदलना एक-लाइन परिवर्तन है। और नियमित रूप से .net उपलब्ध है, जैसा कि मल्टी है। -targeting। बहरहाल, यह चारों ओर आईडीई टूलींग बस भयानक है - तुम सिर्फ पता है कि आप के लिए बदल सकते हैं और कर सकते हैं की जरूरत है क्या :)
मार्क Gravell

57
static object Lock = new object();

lock (Lock) 
{
// do stuff
}

9
क्या आप वाकई अपनी लॉक ऑब्जेक्ट को स्टेटिक घोषित करना चाहते हैं ..?
सर्ग

21
ज़रूर, इसलिए हर थ्रेड आसानी से चारों ओर संदर्भ के बिना इसे एक्सेस कर सकता है।
Jan Gressmann

32
यदि हम प्रश्नकर्ता के प्रश्न के संदर्भ में हैं, तो हम उदाहरण के तरीकों के बारे में बात कर रहे हैं। स्थैतिक का उपयोग करने का मतलब है कि यदि थ्रेड 1 कॉल Inst1.DoSomething () और थ्रेड 2 कॉल्स Inst2.DoSomething कहते हैं, तो दूसरी कॉल ब्लॉक होगी भले ही यह पूरी तरह से अलग वस्तु हो। जब तक कोई एक ही ऑब्जेक्ट पर DoSomething को कॉल नहीं कर रहा है तब तक thread2 की कॉल ब्लॉक नहीं होनी चाहिए । यह कहते हुए कि आप गलत नहीं हैं, लेकिन यह कहना महत्वपूर्ण है कि यहां स्थैतिक का उपयोग करने के प्रभाव को समझना महत्वपूर्ण है, क्योंकि यह प्रति उदाहरण के आधार पर वैश्विक स्तर पर अवरुद्ध करके खराब प्रदर्शन का कारण हो सकता है।
एरोनल्स

1
@AaronLS स्थैतिक लॉक यदि बहुत उपयोगी है जब आपकी वस्तु अपने से बड़े दायरे पर कार्रवाई करती है। हमेशा उदाहरण के लिए वेब-सेवाओं के साथ होता है।
थिबॉल्ट डी।

3
-1 क्योंकि यह एक अलग व्यवहार है जो ओपी पूछ रहा है। यह एक क्लास लॉक है, इंस्टेंस लॉक नहीं।
18

39

क्या c # का java "सिंक्रोनाइज़" कीवर्ड का अपना संस्करण है?

सी # में, आप स्पष्ट रूप से lockसंसाधनों कि आप अतुल्यकालिक धागे पर तुल्यकालिक रूप से काम करना चाहते हैं। lockएक ब्लॉक खोलता है; यह विधि के स्तर पर काम नहीं करता है।

हालाँकि, अंतर्निहित तंत्र रनटाइम पर (और बाद में ) lockइनवाइट करके काम करने के समान है। सन डॉक्यूमेंट के अनुसार जावा उसी तरह काम करता है ।Monitor.EnterMonitor.Exit


3
इसमें एक समतुल्य "कीवर्ड" नहीं है, लेकिन ऊपर दिखाए गए मार्क ग्रेवेल के उत्तर के रूप में, आप [MethodImpl (MethodImplOptions.Synchronized)] एनोटेशन का उपयोग करके विधि स्तर पर सिंक्रनाइज़ कर सकते हैं।
माइंडजुइस

1
चूंकि जावा की synchronizedविधि मूल रूप से synchronized (this.getClass())C # पर समान नहीं है lock(typeof(this))?
श्री हर्ष चिलकपति

2
@ श्रीहरिश्चलाकापति केवल आंशिक रूप से सही है, synchronizedएक विधि पर जावा का कीवर्ड अधिक पसंद है: synchronized(this)केवल एक स्थिर विधि पर यह व्यवहार करता है synchronized(class)
bvdb

7

ध्यान दें, पूर्ण पथ के साथ लाइन: [MethodImpl(MethodImplOptions.Synchronized)]जैसा दिखना चाहिए

[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]


1
या आप सिर्फ उपयोग कर सकते हैंusing System.Runtime.CompilerServices;
aloisdg

मैंने उस टिप्पणी को लिखा था जब मुझे अभी तक स्वचालित रूप से बयानों का उपयोग करने के बारे में नहीं पता था, कुछ दिनों या हफ्तों से अधिक के लिए सी # प्रोग्राम किए जाने के बाद और मैं उन 3 upvotes के बारे में चकित हूं।
Traubenfuchs

1
आपने कम से कम 3
देवों

5

आप lockइसके बजाय कथन का उपयोग कर सकते हैं । मुझे लगता है कि यह केवल दूसरे संस्करण को बदल सकता है। यह भी ध्यान रखें कि दोनों synchronizedऔर lockजरूरत एक वस्तु पर संचालित करने के लिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.