2012-09-06 25 views
12

को देखते हुए:बनाना एक वर्ग थ्रेड-सुरक्षित

public class TestSeven extends Thread { 

private static int x; 

public synchronized void doThings() { 
    int current = x; 
    current++; 
    x = current; 
} 

public void run() { 
    doThings(); 
    } 
} 

कौन सा वाक्य सही है?

ए संकलन विफल रहता है।

बी रनटाइम पर एक अपवाद फेंक दिया गया है।

सी। रन() विधि सिंक्रनाइज़ करने से वर्ग थ्रेड-सुरक्षित हो जाएगा।

डी। परिवर्तनीय "एक्स" में डेटा समवर्ती पहुंच समस्याओं से संरक्षित है।

ई। डॉटिंग्स() विधि को स्थिर के रूप में घोषित करने से वर्ग थ्रेड-सुरक्षित हो जाएगा।

एफ। सिंक्रनाइज़ (नया ऑब्जेक्ट()) {} ब्लॉक में doThings() के भीतर बयानों को लपेटना कक्षा थ्रेड-सुरक्षित बना देगा।

क्या कक्षा थ्रेड-सुरक्षित बनाने के लिए doThings() को सिंक्रनाइज़ करने के लिए पर्याप्त नहीं है? मैं देखता हूं कि सही उत्तर डी है लेकिन इस प्रश्न का मॉडल उत्तर ई है, लेकिन मुझे समझ में नहीं आता क्यों?

उत्तर

17

ई। डॉटिंग्स() विधि को स्थिर के रूप में घोषित करने से वर्ग थ्रेड-सुरक्षित हो जाएगा।

यह एक कठिन जवाब है। विधि पहले ही सिंक्रनाइज़ है, लेकिन उदाहरण पर, जबकि राज्य स्थिर क्षेत्र में है, यानी कक्षा में। इसे static synchronized बनाना वास्तव में सही उत्तर है, क्योंकि तब यह वर्ग पर सिंक्रनाइज़ करता है, न कि (अर्थहीन) उदाहरण पर।

डी। परिवर्तनीय "एक्स" में डेटा समवर्ती पहुंच समस्याओं से संरक्षित है।

private static int x; 

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

11

language spec के अनुसार:

एक सिंक्रनाइज़ विधि एक मॉनिटर (§17.1) से पहले ही कार्यान्वित प्राप्त कर लेता है।

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

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

इसका मतलब यह है कोड में आपके द्वारा दी गई कि synchronized कीवर्ड विधि के शरीर निष्पादित करने से पहले this पर एक ताला प्राप्त करने के लिए विधि का कारण बनता है। हालांकि, xstatic है जो यह सुनिश्चित नहीं करता है कि x पर अद्यतन परमाणु होगा। (वर्ग का एक और उदाहरण सिंक्रनाइज़ क्षेत्र में प्रवेश कर सकता है और एक ही समय में एक अपडेट कर सकता है क्योंकि उनके पास अलग-अलग this मान हैं और इस प्रकार अलग-अलग ताले हैं।)

हालांकि, doStuff स्थैतिक घोषित करने से विधि को सभी लॉक प्राप्त होते हैं (Class पर एक) और इस प्रकार विधि निकाय में पारस्परिक बहिष्कार सुनिश्चित करेगा।

विनिर्देशों वास्तव में वर्तनी की जाती है कि: है

के रूप में एक ही बात

class B { 
    synchronized void doSomething() { 
     // ... 
    } 
} 

सचमुच:

class A { 
    static synchronized void doSomething() { 
     // ... 
    } 
} 

सचमुच के रूप में

class A { 
    static void doSomething() { 
     synchronized(A.class) { 
      // ... 
     } 
    } 
} 
इसी

एक ही बात

class B { 
    void doSomething() { 
     synchronized (this) { 
      // ... 
     } 
    } 
} 
6

doThings() विधि सिंक्रनाइज़ करने के तरीके से, आप किसी विशेष टेस्टसेवन ऑब्जेक्ट के लिए लॉक धारण कर रहे हैं। हालांकि, कक्षा के स्थैतिक चर वस्तु के विशिष्ट उदाहरण से संबंधित नहीं हैं। वे क्लास ऑब्जेक्ट TestSeven.class से संबंधित हैं। तो, या तो आप एक

synchronized (TestSeven.class){ 
    int current = x; 
    current++; 
    x = current; 
} 
अपने doThings अंदर

() विधि जो एक उदाहरण ताला जो बातें अति है अंदर कक्षा ताला प्राप्त करने के लिए जा सकते हैं। इसलिए, आप विधि को स्थिर के रूप में चिह्नित कर सकते हैं ताकि आप कक्षा वर्ग के लॉक को अकेले लॉक कर सकें।

-6

मैं आपसे सहमत हूँ कि सही उत्तर डी है मैं कहूँगा कि ई सही नहीं है क्योंकि अगर मैं doThings() के रूप में स्थिर सेट और सिंक्रनाइज़ कीवर्ड निकालने, मैं सिर्फ 50 TestSeven धागे शुरू कर सकता है और यह हो सकता है गलत एक्स मान में।

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

+3

डी सही नहीं है। – Keppil

+1

ई सही है क्योंकि यह "सिंक्रनाइज़ किए गए कीवर्ड को हटाएं" नहीं कहता है। अनावश्यक रूप से मुश्किल वाक्यांश, लेकिन इन परीक्षाओं में आपको यही मिलता है। – Thilo

+0

डी सही है, क्योंकि दिए गए वर्ग के साथ x के मान को बदलने का कोई और तरीका नहीं है। यदि अन्य विधि जोड़ने की अनुमति है, तो मैं कहूंगा कि समाधान ई भी सही नहीं है। –

1

xstatic अन्य धागे एक ही समय में इसे संशोधित कर सकते हैं doThings विधि चल रही है। doThingsstatic बनाना इसे रोक देगा।