2013-04-22 5 views
13

साथ काम करता है अभ्यास में जावा संगामिति के अनुसार, अध्याय 11.4.3 का कहना है:सरल व्याख्या की जरुरत कैसे "लॉक स्ट्रिपिंग" ConcurrentHashMap

लॉक बंटवारे कभी कभी स्वतंत्र वस्तुओं की एक variablesized सेट पर ताला विभाजन के लिए बढ़ाया जा सकता , जिस स्थिति में इसे लॉक स्ट्रिपिंग कहा जाता है। उदाहरण के लिए, का कार्यान्वयन ConcurrentHashMap 16 ताले की एक सरणी का उपयोग करता है, जिनमें से प्रत्येक हैश बाल्टी के 1/16 गार्ड करता है; बाल्टी एन लॉक एन मोड 16 द्वारा संरक्षित है।

मुझे अभी भी लॉक स्ट्रिपिंग और बाल्टी तंत्र को समझने और कल्पना करने में समस्याएं हैं। क्या कोई इसे अच्छी समझ वाले शब्दों के साथ समझा सकता है :)

अग्रिम धन्यवाद।

उत्तर

30

हैश नक्शा एक सरणी पर बनाया गया है, जहां हैश फ़ंक्शन अंतर्निहित सरणी में किसी तत्व को ऑब्जेक्ट पर मैप करता है। आइए मान लें कि अंतर्निहित सरणी में 1024 तत्व हैं - ConcurrentHashMap वास्तव में इसे 64 तत्वों के 16 विभिन्न उप-सरणी में बदल देता है, उदा। {0, 63}, {64, 127}, आदि। प्रत्येक उप-सरणी का अपना ताला होता है, इसलिए {0, 63} उप-सरणी को संशोधित करने से {64, 127} उप-सरणी - एक धागा प्रभावित नहीं होता है पहले उप-सरणी में लिख सकते हैं जबकि दूसरा धागा दूसरे उप-सरणी में लिखता है।

से अधिक थ्रेड अक्सर एक Collections.synchronizedMap() का उपयोग करेंगे तो बाद से प्रत्येक विधि (यानी अगर एक साझा लॉक का उपयोग कर सिंक्रनाइज़ है, विवाद का एक बहुत वहाँ हो जाएगा: इस प्रकार

+0

ठीक है, मैं समझता हूं। लेकिन क्या होगा यदि दो या दो से अधिक धागे उप-सरणी {0,63} में सभी को संशोधित करने का प्रयास कर रहे हैं? – GedankenNebel

+3

फिर पहली बार पहली बार सेवा की जाती है - ताला हासिल करने वाला पहला धागा इसके परिवर्तन करता है, फिर जब यह दूसरे धागे को समाप्त करता है तो इसके परिवर्तन होते हैं। 'ConcurrentHashMap' में' प्रतिस्थापन 'जैसी विधियां हैं ताकि यह सुनिश्चित किया जा सके कि दूसरा थ्रेड अनजाने में पहले थ्रेड के परिवर्तनों को ओवरराइट नहीं करता है। –

+0

मुझे नहीं लगता कि यह वास्तव में "पहली बार पहली बार सेवा की जाती है," जैसा कि मैं समझता हूं (मेरे पास सटीक उद्धरण नहीं है, लेकिन मैंने इसे अभ्यास में जावा कंसुरेंसी से सीखा है) निष्पक्षता केवल तब ही गारंटी दी जाती है जब यह स्पष्ट हो, रचनाकारों की तरह अलग-अलग स्पष्ट 'लॉक' कार्यान्वयन के लिए, जैसे 'रीन्टेंट्रॉक लॉक', या 'ऐरेब्लॉकिंग क्यूयू' जैसी पंक्तियां। (मुझे पता है कि यह एक पुराना धागा है, क्षमा करें) – Marcelo

11

एक Collections.synchronizedMap() में ताला के बीच का अंतर और एक ConcurrentHashMap है थ्रेड एक्स Collections.synchronizedMap() पर एक विधि को कॉल करता है, अन्य सभी धागे Collections.synchronizedMap() पर किसी भी विधि को कॉल करने से अवरुद्ध कर दिए जाएंगे जब तक कि थ्रेड एक्स उस विधि से वापस न आए)।

ConcurrentHashMap में ताले की एक चर संख्या है (डिफ़ॉल्ट 16 है) प्रत्येक ConcurrentHashMap में चाबियों का एक सेगमेंट रखता है। तो 160 कुंजी के साथ ConcurrentHashMap के लिए, प्रत्येक लॉक 10 तत्वों की रक्षा करेगा। इसलिए, एक कुंजी पर चलने वाली विधियां (get, put, set, आदि ...) केवल उस कुंजी पर चलने वाली अन्य विधियों तक पहुंच को लॉक करें जहां कुंजी एक ही सेगमेंट में हैं। उदाहरण के लिए, यदि थ्रेड एक्स put(0, someObject) पर कॉल करता है, और फिर थ्रेड वाई put(10, someOtherObject) कॉल करता है तो वे कॉल एक साथ निष्पादित कर सकते हैं, और थ्रेड वाई को थ्रेड एक्स के लिए put(0, someObject) से वापस आने की प्रतीक्षा नहीं करनी पड़ती है। एक उदाहरण नीचे प्रदान किया गया है।

इसके अतिरिक्त, size() और isEmpty() जैसी कुछ विधियों की सुरक्षा नहीं की जाती है। हालांकि यह अधिक समवर्तीता के लिए अनुमति देता है, इसका मतलब है कि वे दृढ़ता से संगत नहीं हैं (वे उस स्थिति को प्रतिबिंबित नहीं करेंगे जो समवर्ती रूप से बदल रहा है)।

public static void main(String[] args) { 
    ConcurrentHashMap<Integer, Object> map = new ConcurrentHashMap<>(160); 

    new Thread(new Runnable() { 
    @Override 
    public void run() { 
     map.put(0, "guarded by one lock"); 
    } 
    }.start(); 

    new Thread(new Runnable() { 
    @Override 
    public void run() { 
     map.put(10, "guarded by another lock"); 
    } 
    }.start(); 

    new Thread(new Runnable() { 
    @Override 
    public void run() { 
     // could print 0, 1, or 2 
     System.out.println(map.count()); 
    } 
    }.start(); 
} 
+0

जावा में हैश मैप थ्रेड सुरक्षित नहीं है, हैशटेबल है। आप जिस परिदृश्य के बारे में बात करते हैं वह हैशटेबल के लिए है –

2

यहां मुख्य अवधारणा "बाल्टी" है। इसके बजाय इस पूरे हैश टेबल के लिए वैश्विक लॉक का उपयोग करके, यह प्रत्येक बाल्टी के लिए एक छोटा लॉक का उपयोग करता है। यह बाल्टी सॉर्ट के लिए भी अच्छा है जो सॉर्टिंग जटिलता में सुधार कर सकता है।

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