2010-02-27 17 views
7

का सिंक्रनाइज़ेशन मैं डॉग ली के 'जावा में कंसुरेंसी प्रोग्रामिंग' पुस्तक पर पढ़ रहा हूं। जैसा कि आप जानते हैं, डौग ने मूल रूप से जावा कंसुरेंसी एपीआई लिखा था। हालांकि, कुछ ने मुझे कुछ भ्रम पैदा कर दिया है और मैं इस छोटे से conundrum पर मेरी कुछ राय हासिल करने की उम्मीद कर रहा था!एक कतार

class LinkedQueue { 
    protected Node head = new Node(null); 
    protected Node last = head; 

    protected final Object pollLock = new Object(); 
    protected final Object putLock = new Object(); 

    public void put(Object x) { 
    Node node = new Node(x); 
    synchronized (putLock) {  // insert at end of list 
     synchronized (last) { 
     last.next = node;  // extend list 
     last = node; 
     } 
    } 
    } 

    public Object poll() {   // returns null if empty 
    synchronized (pollLock) { 
     synchronized (head) { 
     Object x = null; 
     Node first = head.next; // get to first real node 
     if (first != null) { 
      x = first.object; 
      first.object = null; // forget old object 
      head = first;   // first becomes new head 
     } 
     return x; 
     } 
    } 
    } 

    static class Node {   // local node class for queue 
    Object object; 
    Node next = null; 

    Node(Object x) { object = x; } 
    } 
} 

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

हालांकि, मैंने जावा कंसुरेंसी लिंक्डब्लॉकिंगक्यूयू को देखा। कतार के original संस्करण सिर या पूंछ पर सिंक्रनाइज़ नहीं करते हैं (मैं भी आधुनिक संस्करण के लिए एक और लिंक पोस्ट करना चाहता था जो एक ही समस्या से पीड़ित है लेकिन मैं ऐसा नहीं कर सका क्योंकि मैं नौसिखिया हूं)। मुझे आश्चर्य है क्यों नहीं? क्या मुझसे कोई चूक हो रही है? क्या जावा मेमोरी मॉडल की मूर्खतापूर्ण प्रकृति का कुछ हिस्सा है जो मुझे याद आ रहा है? मैंने दृश्यता उद्देश्यों के लिए सोचा होगा कि इस सिंक्रनाइज़ेशन की आवश्यकता है? मैं कुछ विशेषज्ञ राय की सराहना करता हूं!

+0

कृपया ध्यान दें, मेरा वर्तमान सिद्धांत 'टेकलॉक' के लिए सिंक्रनाइज़ किए गए ब्लॉक में 'सिग्नल नॉटएक्टी' विधि के बारे में रहता है। यह शायद 'सिर' को देखने के लिए मजबूर करेगा। –

उत्तर

2

संस्करण में आपने नवीनतम जेआरई में संस्करण के साथ-साथ संस्करण भी बनाया है, नोड क्लास के अंदर आइटम अस्थिर है जो सभी अन्य धागे को पढ़ने के लिए पढ़ता है और लिखता है, यहां गहराई से व्याख्या है http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile

+0

धन्यवाद, हाँ अब मैं देखता हूं। एक अस्थिर चर के लिए लिखना एक सिंक्रनाइज़ेशन मॉनिटर जारी करने के समान प्रभाव होगा और इसलिए दृश्यता समस्या हल हो जाती है। –

2

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

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

दृश्यता एक मुद्दा है जब कतार लगभग खाली है, शेष समय() और मतदान() कतार के विभिन्न सिरों पर काम करता है और एक दूसरे के साथ हस्तक्षेप नहीं करता है।

+0

उत्तर के लिए धन्यवाद। यह दिलचस्प है कि सिर और आखिरी सिंक्रनाइज़ेशन के आसपास यहां मुख्य मुद्दा वास्तव में दृश्यता है। यह देखना दिलचस्प है कि एक वैकल्पिक माध्यम से concurrency पैकेज के LinkedBlockingQueue में दृश्यता कैसे प्राप्त की जाती है। यह वास्तव में मुझे साजिश है। –

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