जावा स्थिर स्थिर तरीके: ऑब्जेक्ट या क्लास पर लॉक


148

जावा प्रलेखन कहता है:

इंटरलेव के लिए एक ही वस्तु पर सिंक्रनाइज़ किए गए तरीकों के दो आह्वान संभव नहीं है।

स्थैतिक विधि के लिए इसका क्या अर्थ है? चूंकि किसी स्थिर विधि में कोई संबद्ध ऑब्जेक्ट नहीं है, तो क्या ऑब्जेक्ट के बजाय क्लास पर सिंक्रनाइज़ कीवर्ड लॉक होगा?

जवाबों:


129

चूंकि किसी स्थिर विधि में कोई संबद्ध ऑब्जेक्ट नहीं है, तो क्या ऑब्जेक्ट के बजाय क्लास पर सिंक्रनाइज़ कीवर्ड लॉक होगा?

हाँ। :)


81
कृपया विस्तृत जवाब दें ताकि हर कोई समझ सके।
मधु

6
@Madhu। इसका मतलब है कि यदि आपके पास एक ही कक्षा में 2 या अधिक सिंक्रनाइज़ किए गए तरीके हैं, तो दोनों एक ही समय में निष्पादित नहीं कर सकते हैं, भले ही उस वर्ग के कई उदाहरण हों। लॉकिंग अनिवार्य रूप से प्रत्येक सिंक्रनाइज़ विधि के लिए Object.class पर लॉकिंग के समान है।
स्टीवन

यह उत्तर गलत है - thisउदाहरण के तरीकों पर अधिग्रहित ताला है- , कृपया इसे ऑस्कर ठीक करें।
vemv

1
@vemv प्रश्न वर्ग विधियों से संबंधित है, उदाहरण के तरीकों से नहीं।
ऑस्कर रेज़

23
@vemv ठीक है, उत्तर को समझने के लिए आपको पहले प्रश्न को पढ़ना होगा।
OscarRyz

199

ऑस्कर के लिए थोड़ा विस्तार से जोड़ने के लिए (सुखदायक रसीला!) उत्तर, जावा भाषा विशिष्टता पर संबंधित अनुभाग 8.4.3.6, 'सिंक्रोनाइज़्ड मेथड्स' है :

निष्पादित होने से पहले एक समन्वित विधि एक मॉनिटर ( .17.1 ) प्राप्त करती है । एक वर्ग (स्थिर) विधि के लिए, विधि के वर्ग के लिए क्लास ऑब्जेक्ट से जुड़े मॉनिटर का उपयोग किया जाता है। एक उदाहरण विधि के लिए, इस के साथ जुड़े मॉनिटर (जिस वस्तु के लिए विधि लागू की गई थी) का उपयोग किया जाता है।


17
उपयोगी, मैं
ऑस्कररेज़

80

एक बिंदु पर आपको सावधान रहना होगा (कई प्रोग्रामर आम तौर पर उस जाल में पड़ जाते हैं) यह है कि सिंक्रनाइज़ स्थिर विधियों और सिंक गैर-स्थिर तरीकों के बीच कोई लिंक नहीं है, अर्थात:

class A {
    static synchronized f() {...}
    synchronized g() {...}
}

मुख्य:

A a = new A();

धागा 1:

A.f();

धागा 2:

a.g();

एफ () और जी () एक दूसरे के साथ सिंक्रनाइज़ नहीं हैं और इस तरह पूरी तरह से समवर्ती निष्पादित कर सकते हैं।


18
लेकिन क्या होगा अगर g () कुछ स्थिर चर को बदल रहा है जो f () पढ़ रहा है। हम उस धागे को सुरक्षित कैसे बनाते हैं? क्या हम स्पष्ट रूप से कक्षा पर ताला लगाते हैं?
बेसकिन

22
हाँ, अपने गैर स्थैतिक विधि स्पष्ट रूप से कक्षा में ही (यानी, पर सिंक्रनाइज़ करना चाहिए synchronized (MyClass.class) {...}
jfpoilpret

@jfpoilpret "सिंक्रोनाइज़ (MyClass.class) {...}" इस विधि को स्टैटिक सिंक्रनाइज़ करने के लिए बराबर है, है ना?
crazymind

15

जब तक आप जी लागू नहीं करते हैं () निम्नानुसार है:

g() {
    synchronized(getClass()) {
        ...
    }
}

मुझे यह पैटर्न तब भी उपयोगी लगता है जब मैं वस्तु के विभिन्न उदाहरणों के बीच आपसी बहिष्करण को लागू करना चाहता हूं (जो कि जब किसी बाहरी संसाधन के उदाहरण के लिए आवश्यक होता है)।


63
ध्यान दें कि वास्तव में यहां कुछ बहुत ही सूक्ष्म और गंदा कीड़े का मौका हो सकता है। याद रखें getClass()रिटर्न क्रम प्रकार; यदि आप कक्षा को उपवर्गित करते हैं, तो अभिभावक वर्ग और बालक वर्ग अलग-अलग तालों पर सिंक्रनाइज़ हो जाएंगे। synchronized(MyClass.class)जाने के लिए रास्ता है अगर आपको यह सुनिश्चित करने की आवश्यकता है कि सभी उदाहरण एक ही लॉक का उपयोग करें।
कोवान

4

आंतरिक ताले और तुल्यकालन पर oracle प्रलेखन पृष्ठ पर एक नज़र है

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


2

एक स्थैतिक विधि में एक संबद्ध वस्तु भी होती है। यह JDK टूलकिट में Class.class फ़ाइल के अंतर्गत आता है। जब .class फ़ाइल RAM में लोड होती है, तो Class.class इसका एक उदाहरण बनाता है जिसे टेम्पलेट ऑब्जेक्ट कहा जाता है।

जैसे: - जब आप मौजूदा ग्राहक वर्ग से ऑब्जेक्ट बनाने की कोशिश करते हैं जैसे

Customer c = new Customer();

Customer.class RAM में लोड होता है। उस पल में JDK टूलकिट में Class.class, टेम्पलेट ऑब्जेक्ट नामक एक ऑब्जेक्ट बनाता है और उस टेम्पलेट ऑब्जेक्ट में Customer.class लोड करता है। उस Customer.class के सदस्य उस टेम्पलेट ऑब्जेक्ट में विशेषताएँ और विधियाँ बन जाते हैं।

तो एक स्थिर विधि या विशेषता में भी एक वस्तु है


2

नीचे दिए गए उदाहरण क्लास और ऑब्जेक्ट लॉक के बीच अधिक स्पष्टता प्रदान करते हैं, आशा है कि नीचे दिए गए उदाहरण दूसरों को भी मदद करेंगे :)

उदाहरण के लिए हमारे पास निम्न विधियाँ हैं एक वर्ग को प्राप्त करने और दूसरी वस्तु को प्राप्त करने के लिए ताला:

public class MultiThread {

    public static synchronized void staticLock() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
    }

    public synchronized void objLock() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
    }
}

तो, अब हम निम्नलिखित परिदृश्य हो सकते हैं:

  1. जब एक ही वस्तु का उपयोग करने वाले धागे एक ही समय objLock या staticLock विधि तक पहुंचने की कोशिश करते हैं (यानी दोनों धागे एक ही विधि का उपयोग करने की कोशिश कर रहे हैं)

    Thread-0 0
    Thread-0 1
    Thread-0 2
    Thread-0 3
    Thread-0 4
    Thread-1 0
    Thread-1 1
    Thread-1 2
    Thread-1 3
    Thread-1 4
    
  2. का उपयोग करते हुए धागे जब एक ही वस्तु का उपयोग करने की कोशिश करता staticLockहै और objLockपद्धतियां ठीक उसी समय (कोशिश करता विभिन्न तरीकों एक्सेस करने वाले)

    Thread-0 0
    Thread-1 0
    Thread-0 1
    Thread-1 1
    Thread-0 2
    Thread-1 2
    Thread-1 3
    Thread-0 3
    Thread-0 4
    Thread-1 4
    
  3. जब अलग-अलग ऑब्जेक्ट का उपयोग करके थ्रेड्स पहुंच staticLockविधि का उपयोग करता है

    Thread-0 0
    Thread-0 1
    Thread-0 2
    Thread-0 3
    Thread-0 4
    Thread-1 0
    Thread-1 1
    Thread-1 2
    Thread-1 3
    Thread-1 4
    
  4. जब अलग-अलग ऑब्जेक्ट का उपयोग करके थ्रेड्स पहुंच objLockविधि का उपयोग करता है

    Thread-0 0
    Thread-1 0
    Thread-0 1
    Thread-1 1
    Thread-0 2
    Thread-1 2
    Thread-1 3
    Thread-0 3
    Thread-0 4
    Thread-1 4
    

0

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

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