ConcurrentHashMap और Collections.synchronizedMap (Map) के बीच क्या अंतर है?


607

मेरे पास एक मानचित्र है जिसे कई धागों द्वारा समवर्ती रूप से संशोधित किया जाना है।

जावा एपीआई में तीन अलग-अलग सिंक्रनाइज़ मानचित्र कार्यान्वयन प्रतीत होते हैं:

  • Hashtable
  • Collections.synchronizedMap(Map)
  • ConcurrentHashMap

जो मैं समझता हूं, Hashtableवह एक पुराना कार्यान्वयन (अप्रचलित Dictionaryवर्ग का विस्तार ) है, जिसे बाद में Mapइंटरफ़ेस में फिट करने के लिए अनुकूलित किया गया है। हालांकि यह है सिंक्रनाइज़, यह गंभीर है लगता है scalability मुद्दों और नई परियोजनाओं के लिए हतोत्साहित किया जाता है।

लेकिन बाकी दो का क्या? मैप द्वारा दिए गए Collections.synchronizedMap(Map)और ConcurrentHashMapएस के बीच अंतर क्या हैं ? कौन सी स्थिति में कौन सा फिट बैठता है?


7
@SmilesinaJar लिंक वर्तमान में टूट गया है, यहाँ इस लेख की एक संग्रहित प्रति है: क्यों ConcurrentHashMap Hashtable से बेहतर है और बस के रूप में एक HashMap अच्छा के रूप में
informatik01

2
आईबीएम: कैसे ConcurrentHashMap धागा सुरक्षा से समझौता किए बिना @ उच्च संगामिति प्रस्तावों ibm.com/developerworks/java/library/j-jtp08223/...
pramodc84

FYI करें, जावा 6 ConcurrentSkipListMapएक और थ्रेड-सुरक्षित Mapकार्यान्वयन के रूप में लाया गया । स्किप सूची एल्गोरिदम का उपयोग करते हुए, लोड के तहत अत्यधिक समवर्ती बनाया गया है ।
बेसिल बोर्क

जवाबों:


423

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

यदि आपको डेटा संगति सुनिश्चित करने की आवश्यकता है, तो दूसरे विकल्प का उपयोग करें, और प्रत्येक थ्रेड को मानचित्र के अप-टू-डेट दृश्य की आवश्यकता होती है। यदि प्रदर्शन महत्वपूर्ण है, तो पहले का उपयोग करें, और प्रत्येक थ्रेड केवल मानचित्र में डेटा सम्मिलित करता है, जिसमें रीड अक्सर कम होता है।


8
स्रोत कोड को देखते हुए, सिंक्रनाइज़्ड मैप केवल एक म्यूटेक्स (ब्लॉकिंग) के साथ एक कार्यान्वयन है, जबकि समवर्ती
हाशिए पर

123
कृपया यह भी ध्यान दें कि ConcurrentHashMap रिक्त कुंजियों या मानों की अनुमति नहीं देता है। इसलिए वे एक सिंक्रनाइज़ मानचित्र के समान विकल्प नहीं हैं।
onejigtwojig

24
मुझे लगता है कि आपको यह पढ़ना चाहिए http://ria101.wordpress.com/2011/12/12/concurrenthashmap-avoid-a-common-misuse/
श्री स्पार्क

5
@AddullahShaikh उस लेख में उठाया गया मुद्दा जावा 7 में तय किया गया है और जावा 8 में और सुधार किए गए हैं।
pul0ne

5
@ फेंगएक्सएक्स: जैसे ही आप एक ऑपरेशन कर रहे हैं जिसमें कई प्रश्नों या नक्शे के अपडेट शामिल हैं या जब आप नक्शे पर पुनरावृत्ति कर रहे हैं, तो आपको निरंतरता सुनिश्चित करने के लिए मैन्युअल रूप से मानचित्र पर सिंक्रनाइज़ करना होगा। मैप पर सिंक्रनाइज़ किए गए नक्शे केवल एकल संचालन (विधि इनवोकेशन) के लिए निरंतरता की गारंटी देते हैं, जो इसे अक्सर बेकार से अधिक बनाता है क्योंकि अधिकांश वास्तविक जीवन संचालन गैर-तुच्छ होते हैं, इसलिए आपको मैन्युअल रूप से वैसे भी सिंक्रनाइज़ करना होगा।
होल्गर

241
╔═══════════════╦═══════════════════╦═══════════════════╦═════════════════════╗
║   Property    ║     HashMap       ║    Hashtable      ║  ConcurrentHashMap  ║
╠═══════════════╬═══════════════════╬═══════════════════╩═════════════════════╣ 
║      Null     ║     allowed       ║              not allowed                ║
║  values/keys  ║                   ║                                         ║
╠═══════════════╬═══════════════════╬═════════════════════════════════════════╣
║ Thread-safety ║                   ║                                         ║
║   features    ║       no          ║                  yes                    ║
╠═══════════════╬═══════════════════╬═══════════════════╦═════════════════════╣
║     Lock      ║       not         ║ locks the whole   ║ locks the portion   ║        
║  mechanism    ║    applicable     ║       map         ║                     ║ 
╠═══════════════╬═══════════════════╩═══════════════════╬═════════════════════╣
║   Iterator    ║               fail-fast               ║ weakly consistent   ║ 
╚═══════════════╩═══════════════════════════════════════╩═════════════════════╝

लॉकिंग मैकेनिज्म के बारे में: Hashtable ऑब्जेक्ट को लॉक करता है , जबकि केवल बकेट को ConcurrentHashMapलॉक करता है


13
Hashtableनक्शे के हिस्से को लॉक नहीं कर रहा है। कार्यान्वयन को देखो। यह synchronizedबिना किसी लॉक के कुंजी का उपयोग कर रहा है, इसलिए इसका मूल रूप से मतलब है कि यह hashtableप्रत्येक ऑपरेशन में पूरे लॉक है ।
RMachnik

6
सिंक्रोनाइज़ के बारे में क्या?
शमूएल एडविन वार्ड

3
कलेक्शंस.सिंक्रोनाइज़्ड मैप व्यवहार बैकिंग मैप की तरह है, सिवाय इसके सभी तरीके थ्रेड-सुरक्षित हैं
सर्जी शेवचेक

5
मैं तालिका छापता और $ 5 प्रत्येक को बेच देता;)। गुड @ @शेविक
realPK

संपादित: न तो पूरी तरह से थ्रेड सुरक्षित हैं। यह नए डेवलपर्स के लिए थोड़ा भ्रामक है। देखें: ibm.com/developerworks/java/library/j-jtp07233/index.html यह समझने के लिए कि यहां तक ​​कि समवर्ती हाशपा भी बाहरी डेटा-दौड़ से पूरी तरह से सुरक्षित नहीं है। (उदाहरण: 1 थ्रेड एक मान निकालता है और दूसरा बाद में जाँच करता है कि क्या यह मौजूद है और यदि नहीं है तो डाल दें। यह डेटा रेस की स्थिति है और फिर भी इसका मतलब है कि "कॉन्ट्रैक्शनल हाशप" का उपयोग करने के बावजूद आपको सभी थ्रेड सुरक्षा समस्याओं से छुटकारा नहीं मिलता है।
लाश

142

के लिए "मापनीयता के मुद्दे" Hashtableबिल्कुल उसी तरह से मौजूद हैं Collections.synchronizedMap(Map)- वे बहुत ही सरल सिंक्रनाइज़ेशन का उपयोग करते हैं, जिसका अर्थ है कि केवल एक धागा एक ही समय में मानचित्र तक पहुंच सकता है।

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

ConcurrentHashMapसिंक्रनाइज़ेशन की आवश्यकता को कम करने के लिए बहुत परिष्कृत तकनीकों का उपयोग करता है और सिंक्रनाइज़ेशन के बिना कई थ्रेड्स द्वारा समानांतर रीड एक्सेस की अनुमति देता है और, इससे भी महत्वपूर्ण बात Iteratorयह है कि कोई सिंक्रनाइज़ेशन की आवश्यकता नहीं है और यहां तक ​​कि मैप को हस्तक्षेप के दौरान संशोधित करने की अनुमति देता है (हालांकि यह कोई गारंटी नहीं देता है कि या नहीं वे तत्व जो पुनरावृत्ति के दौरान डाले गए थे) वापस आ जाएंगे।


4
अब यही तो मैं चाहता था! :) नहीं-सिंक्रनाइज़ किए गए Iterator सिर्फ शुद्ध मिठास है! जानकारी के लिए धन्यवाद! :) (:
कौंनवी

शानदार उत्तर..लेकिन इसका मतलब यह है कि रिट्रीवल थ्रेड के दौरान नवीनतम अपडेट नहीं मिलेगा क्योंकि पाठक थ्रेड सिंक में नहीं हैं।
MrA

@ मेर: क्या आप समवर्ती हाशपा के बारे में पूछ रहे हैं? और "रिट्रीवल" से आपका क्या तात्पर्य है?
माइकल बोर्गवर्ड

4
@Michael Borgwardt उदाहरण के लिए समवर्ती हैशमैप के लिए। मान लीजिए कि कई सूत्र हैं। उनमें से कुछ मैप को अपडेट कर रहे हैं और उनमें से कुछ उसी मैप से डेटा प्राप्त कर रहे हैं। इस परिदृश्य में, जब थ्रेड्स पढ़ने की कोशिश कर रहे हैं, तो क्या यह गारंटी है कि उन्हें नवीनतम डेटा मिलेगा जिसे अपडेट किया गया है क्योंकि पाठक थ्रेड्स को ताले रखने की आवश्यकता नहीं है।
MrA

35

जब आप इसका उपयोग कर सकते हैं, तो ConcurrentHashMap पसंद किया जाता है - हालांकि इसके लिए कम से कम जावा 5 की आवश्यकता होती है।

यह कई थ्रेड्स द्वारा उपयोग किए जाने पर अच्छी तरह से स्केल करने के लिए डिज़ाइन किया गया है। प्रदर्शन केवल एक समय में मानचित्र तक पहुँचने पर केवल एक धागे से, लेकिन बहुत बेहतर होता है जब कई सूत्र मानचित्र पर समान रूप से पहुँचते हैं, तो यह बहुत कम हो सकता है।

मुझे एक ब्लॉग प्रविष्टि मिली जो उत्कृष्ट पुस्तक Java Concurrency In Practice की एक तालिका को पुन: प्रस्तुत करती है , जिसे मैं अच्छी तरह से हूं।

Collections.synchronizedMap वास्तव में केवल तभी समझ में आता है जब आपको कुछ अन्य विशेषताओं के साथ मानचित्र को लपेटने की आवश्यकता होती है, शायद कुछ प्रकार के ऑर्डर किए गए नक्शे, जैसे कि एक TreeMap।


2
हाँ - लगता है कि मैं उस पुस्तक का उल्लेख करता हूं, जो मैं करता हूं!
बिल माइकेल

@BillMichell लिंक टूटा है

@ गोविंदा लिंक एक्सेस करने से पहले जावास्क्रिप्ट बंद कर दें। ब्लॉग प्रविष्टि अभी भी वहाँ है!
बिल माइकल

32

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

एक अन्य अंतर यह भी है कि ConcurrentHashMapपास किए गए मैप में तत्वों के क्रम को संरक्षित नहीं किया जाएगा। यह HashMapडेटा संग्रहीत करते समय समान है । इस बात की कोई गारंटी नहीं है कि तत्व आदेश संरक्षित है। जबकि Collections.synchronizedMap()पास किए गए मानचित्र के तत्वों के क्रम को संरक्षित करेगा। उदाहरण के लिए, यदि आप एक TreeMapको पास करते हैं ConcurrentHashMap, तो ConcurrentHashMapहो सकता है कि तत्व क्रम उसी क्रम में न हों TreeMap, लेकिनCollections.synchronizedMap() आदेश को संरक्षित करेगा।

इसके अलावा, ConcurrentHashMapगारंटी दे सकता है कि कोई ConcurrentModificationExceptionथ्रेड नहीं है, जबकि एक थ्रेड मैप को अपडेट कर रहा है और दूसरा थ्रेड मैप से प्राप्त इट्रेटर को ट्रेस कर रहा है। तथापि,Collections.synchronizedMap() इस पर गारंटी नहीं है।

नहीं है एक पोस्ट जो इन दोनों और भी के मतभेदों का प्रदर्शन ConcurrentSkipListMap


13

सिंक्रोनाइज़्ड मैप:

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

ConcurrentHashMap:

ConcurrentHashMap वर्ग मानक HashMap का समवर्ती संस्करण प्रदान करता है। यह संग्रह वर्ग में प्रदान की गई सिंक्रोनाइज़ कार्यक्षमता पर सुधार है।

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

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

ConcurrentHashMap एक ConcurrentModificationException नहीं फेंकता है

यदि एक धागा इसे संशोधित करने की कोशिश कर रहा है, तो दूसरा समवर्ती है।

सिंक्रोनाइज्ड मैप और कॉनकॉन्ट्रश हाशिएप के बीच अंतर

Collections.synchornizedMap (HashMap) एक संग्रह लौटाएगा जो लगभग Hashtable के बराबर है, जहां Map के हर संशोधन ऑपरेशन को Map Object पर लॉक किया जाता है जबकि ConcurrentHashMap के मामले में, थ्रेड-सेफ्टी संपूर्ण मैप को अलग-अलग विभाजन के आधार पर संगणना स्तर पर विभाजित करके हासिल की जाती है। और पूरे मानचित्र को लॉक करने के बजाय केवल विशेष भाग को लॉक करना।

समवर्ती HashMap null कुंजियों या अशक्त मानों की अनुमति नहीं देता है जबकि सिंक्रनाइज़ HashMap एक अशक्त कुंजियों की अनुमति देता है।

इसी तरह के लिंक

link1

link2

प्रदर्शन की तुलना


12
  • Hashtableऔर कुंजी या मान की ConcurrentHashMapअनुमति न दें ।nullnull

  • Collections.synchronizedMap(Map)सिंक्रनाइज़ करता है सभी परिचालन ( get, put, size, आदि)।

  • ConcurrentHashMap अद्यतन के लिए पुनर्प्राप्ति की पूर्ण संगति, और समायोज्य अपेक्षित संगामिति का समर्थन करता है।

हमेशा की तरह, वहाँ संगामिति हैं - ओवरहेड - स्पीड ट्रेडऑफ़ शामिल हैं। आपको वास्तव में निर्णय लेने के लिए अपने आवेदन की विस्तृत संगामिति आवश्यकताओं पर विचार करने की आवश्यकता है, और फिर यह देखने के लिए अपने कोड का परीक्षण करें कि क्या यह पर्याप्त है।


12

में ConcurrentHashMap, ताला एक खंड के बजाय एक पूरे मानचित्र पर लागू होता है। प्रत्येक खंड अपनी आंतरिक हैश तालिका का प्रबंधन करता है। ताला केवल अद्यतन कार्यों के लिए लागू किया जाता है। Collections.synchronizedMap(Map)पूरे नक्शे को सिंक्रनाइज़ करता है।


क्या आप कृपया एक नज़र stackoverflow.com/questions/48579060/… ले सकते हैं ?
gstackoverflow

9

आप इसके बारे में सही हैं HashTable, आप इसके बारे में भूल सकते हैं।

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

synchronized (records) {
  Record rec = records.get(id);
  if (rec == null) {
      rec = new Record(id);
      records.put(id, rec);
  }
  return rec;
}

हालांकि, ऐसा मत सोचो कि एक सामान्य ब्लॉक के साथ एक ConcurrentHashMapसरल विकल्प है जैसा कि ऊपर दिखाया गया है। इसकी पेचीदगियों को बेहतर तरीके से समझने के लिए इस लेख को पढ़ें ।HashMapsynchronized


7

यहाँ कुछ हैं:

1) ConcurrentHashMap केवल मैप के कुछ हिस्सों को लॉक करता है, लेकिन SynchronizedMap पूरे एमएपी को लॉक करता है।
2) समवर्ती हाशिए पर सिंक्रोनाइज्ड स्पाट से बेहतर प्रदर्शन और अधिक स्केलेबल है।
3) कई पाठक और एकल लेखक समवर्ती हाशपा के मामले में सबसे अच्छा विकल्प है।

यह पाठ जावा में ConcurrentHashMap और हैशटेबल के बीच अंतर से है


7

हम समवर्ती HashMap और सिंक्रोनाइज़्ड Hashmap और Hashtable का उपयोग करके थ्रेड सुरक्षा प्राप्त कर सकते हैं। लेकिन अगर आप उनकी वास्तुकला को देखें तो बहुत अंतर है।

  1. सिंक्रोनाइज़्ड हाशमैप और हैशटेबल

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

  1. ConcurrentHashMap

यह खंड स्तर पर ताला बनाए रखेगा। इसके 16 खंड हैं और डिफ़ॉल्ट रूप से समवर्ती स्तर को 16 बनाए रखता है। तो एक समय में, 16 सूत्र समवर्ती HashMap पर संचालित करने में सक्षम हो सकते हैं। इसके अलावा, रीड ऑपरेशन को लॉक की आवश्यकता नहीं होती है। तो किसी भी संख्या में धागे उस पर एक ऑपरेशन कर सकते हैं।

यदि thread1 खंड 2 में पुट ऑपरेशन करना चाहता है और thread2 खंड 4 पर पुट ऑपरेशन करना चाहता है तो इसे यहां अनुमति है। मतलब, 16 धागे एक समय में समवर्ती हाशप पर अपडेट (पुट / डिलीट) ऑपरेशन कर सकते हैं।

ताकि यहां इंतजार का समय कम रहे। इसलिए प्रदर्शन सिंक्रोनाइज्ड हैशमैप और हैशटेबल की तुलना में अपेक्षाकृत बेहतर है।


1
, 1। यदि एकाधिक थ्रेड एक ही ब्लॉक को संपादित करने की कोशिश करता है तो क्या होगा? 2. क्या होता है अगर दो धागे एक ही ब्लॉक से डेटा पढ़ने की कोशिश करते हैं जहां एक और धागा एक ही समय में डेटा लिखता है?
प्रिन्जन

6

ConcurrentHashMap

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

SynchronizedHashMap

  • वस्तु स्तर पर तुल्यकालन।
  • हर रीड / राइट ऑपरेशन को लॉक हासिल करने की जरूरत होती है।
  • पूरे संग्रह को लॉक करना एक प्रदर्शन ओवरहेड है।
  • यह अनिवार्य रूप से पूरे नक्शे के लिए केवल एक थ्रेड को एक्सेस देता है और अन्य सभी थ्रेड्स को ब्लॉक करता है।
  • इससे विवाद पैदा हो सकता है।
  • सिंक्रोनाइज़्ड हाशपेर Iterator देता है, जो समवर्ती संशोधन पर तेजी से विफल होता है।

स्रोत


4

समवर्ती हाशिए समवर्ती पहुंच के लिए अनुकूलित है।

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


4

वहाँ एक महत्वपूर्ण सुविधा है ConcurrentHashMapजो इसे प्रदान करता है, जो विफल-सुरक्षित पुनरावृत्ति है, के अलावा अन्य के बारे में ध्यान दें । मैंने डेवलपर्स को ConcurrentHashMapसिर्फ इसलिए इस्तेमाल करते हुए देखा है क्योंकि वे एंट्रीसेट को संपादित करना चाहते हैं - इस पर पुनरावृत्ति करते हुए इसे हटा दें। विफल-सुरक्षित पुनरावृत्ति Collections.synchronizedMap(Map)प्रदान नहीं करता है, बल्कि इसके स्थान पर विफल-तेज़ पुनरावृत्ति प्रदान करता है । असफल-तेज़ पुनरावृत्तियाँ मानचित्र के आकार के स्नैपशॉट का उपयोग करती हैं जिसे पुनरावृति के दौरान संपादित नहीं किया जा सकता है।


3
  1. यदि डेटा संगति अत्यधिक महत्वपूर्ण है - हैशटेबल या कलेक्शंस का उपयोग करें। SynchronizedMap (Map)।
  2. यदि गति / प्रदर्शन अत्यधिक महत्वपूर्ण है और डेटा अपडेटिंग से समझौता किया जा सकता है- तो ConcurrentHashMap का उपयोग करें।

2

सामान्य तौर पर, यदि आप ConcurrentHashMapयह सुनिश्चित करना चाहते हैं कि आप 'अपडेट' को मिस करने के लिए तैयार हैं
(यानी हाशप की प्रिंटिंग सामग्री यह सुनिश्चित नहीं करती है कि यह अप-टू-डेट मैप को प्रिंट करेगा) और एपीआई का उपयोग करना चाहते CyclicBarrierहैं ताकि आपके कार्यक्रम में निरंतरता सुनिश्चित हो सके जीवन चक्र।


1

Collections.synchronizedMap () विधि, HashMap के सभी तरीकों को सिंक्रनाइज़ करती है और इसे प्रभावी ढंग से एक डेटा संरचना में कम करती है जहां एक समय में एक धागा दर्ज हो सकता है क्योंकि यह प्रत्येक विधि को एक सामान्य लॉक पर लॉक करता है।

समवर्ती HashMap सिंक्रनाइज़ेशन में थोड़ा अलग तरीके से किया जाता है। प्रत्येक विधि को एक आम लॉक पर लॉक करने के बजाय, कॉनकरेन्थ हाशप अलग बाल्टी के लिए अलग-अलग लॉक का उपयोग करता है और इस प्रकार मैप के केवल एक हिस्से को लॉक करता है। डिफ़ॉल्ट रूप से 16 बाल्टियाँ हैं और अलग-अलग बाल्टियों के लिए अलग-अलग ताले भी हैं। तो डिफ़ॉल्ट समाप्य स्तर 16 है। इसका मतलब है कि सैद्धांतिक रूप से किसी भी समय 16 धागे समवर्ती हाशप का उपयोग कर सकते हैं यदि वे सभी अलग-अलग बाल्टी में जा रहे हैं।


1

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

कैसे समवर्ती HashMap कार्यान्वित किया जाता है

ConcurrentHashMap को हैशटेबल के विकल्प के रूप में विकसित किया गया था और अतिरिक्त क्षमता के साथ हैशटेबल की सभी कार्यक्षमता का समर्थन करता है, इसलिए इसे संगामिती स्तर कहा जाता है। ConcurrentHashMap कई पाठकों को ब्लॉकों का उपयोग किए बिना एक साथ पढ़ने की अनुमति देता है। मैप को अलग-अलग हिस्सों में अलग करना और अपडेट में मैप के केवल हिस्से को ब्लॉक करना संभव हो जाता है। डिफ़ॉल्ट रूप से, संगामिति का स्तर 16 है, इसलिए मानचित्र को 16 भागों में विभाजित किया गया है और प्रत्येक भाग को अलग ब्लॉक द्वारा प्रबंधित किया गया है। इसका मतलब है, कि 16 धागे मैप के साथ एक साथ काम कर सकते हैं, अगर वे मैप के विभिन्न हिस्सों के साथ काम करते हैं। यह समवर्ती हाईशोप हाईट को उत्पादक बनाता है, न कि थ्रेड-सेफ्टी को डाउन करने के लिए।

यदि आप ConcurrentHashMap की कुछ महत्वपूर्ण विशेषताओं में रुचि रखते हैं और जब आपको मानचित्र के इस बोध का उपयोग करना चाहिए - मैंने सिर्फ एक अच्छे लेख के लिए एक लिंक डाला है - जावा में ConcurrentHashMap का उपयोग कैसे करें


0

इसके अलावा जो सुझाव दिया गया है, मैं उससे संबंधित स्रोत कोड पोस्ट करना चाहूंगा SynchronizedMap

एक Mapधागा सुरक्षित बनाने के लिए , हम उपयोग कर सकते हैंCollections.synchronizedMap कथन का और पैरामीटर के रूप में मानचित्र उदाहरण इनपुट ।

के कार्यान्वयन synchronizedMapमें Collectionsनीचे की तरह है

   public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
        return new SynchronizedMap<>(m);
    }

जैसा कि आप देख सकते हैं, इनपुट Mapऑब्जेक्ट ऑब्जेक्ट द्वारा लपेटा गया है SynchronizedMap
के कार्यान्वयन में खुदाई करते हैं SynchronizedMap,

 private static class SynchronizedMap<K,V>
        implements Map<K,V>, Serializable {
        private static final long serialVersionUID = 1978198479659022715L;

        private final Map<K,V> m;     // Backing Map
        final Object      mutex;        // Object on which to synchronize

        SynchronizedMap(Map<K,V> m) {
            this.m = Objects.requireNonNull(m);
            mutex = this;
        }

        SynchronizedMap(Map<K,V> m, Object mutex) {
            this.m = m;
            this.mutex = mutex;
        }

        public int size() {
            synchronized (mutex) {return m.size();}
        }
        public boolean isEmpty() {
            synchronized (mutex) {return m.isEmpty();}
        }
        public boolean containsKey(Object key) {
            synchronized (mutex) {return m.containsKey(key);}
        }
        public boolean containsValue(Object value) {
            synchronized (mutex) {return m.containsValue(value);}
        }
        public V get(Object key) {
            synchronized (mutex) {return m.get(key);}
        }

        public V put(K key, V value) {
            synchronized (mutex) {return m.put(key, value);}
        }
        public V remove(Object key) {
            synchronized (mutex) {return m.remove(key);}
        }
        public void putAll(Map<? extends K, ? extends V> map) {
            synchronized (mutex) {m.putAll(map);}
        }
        public void clear() {
            synchronized (mutex) {m.clear();}
        }

        private transient Set<K> keySet;
        private transient Set<Map.Entry<K,V>> entrySet;
        private transient Collection<V> values;

        public Set<K> keySet() {
            synchronized (mutex) {
                if (keySet==null)
                    keySet = new SynchronizedSet<>(m.keySet(), mutex);
                return keySet;
            }
        }

        public Set<Map.Entry<K,V>> entrySet() {
            synchronized (mutex) {
                if (entrySet==null)
                    entrySet = new SynchronizedSet<>(m.entrySet(), mutex);
                return entrySet;
            }
        }

        public Collection<V> values() {
            synchronized (mutex) {
                if (values==null)
                    values = new SynchronizedCollection<>(m.values(), mutex);
                return values;
            }
        }

        public boolean equals(Object o) {
            if (this == o)
                return true;
            synchronized (mutex) {return m.equals(o);}
        }
        public int hashCode() {
            synchronized (mutex) {return m.hashCode();}
        }
        public String toString() {
            synchronized (mutex) {return m.toString();}
        }

        // Override default methods in Map
        @Override
        public V getOrDefault(Object k, V defaultValue) {
            synchronized (mutex) {return m.getOrDefault(k, defaultValue);}
        }
        @Override
        public void forEach(BiConsumer<? super K, ? super V> action) {
            synchronized (mutex) {m.forEach(action);}
        }
        @Override
        public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
            synchronized (mutex) {m.replaceAll(function);}
        }
        @Override
        public V putIfAbsent(K key, V value) {
            synchronized (mutex) {return m.putIfAbsent(key, value);}
        }
        @Override
        public boolean remove(Object key, Object value) {
            synchronized (mutex) {return m.remove(key, value);}
        }
        @Override
        public boolean replace(K key, V oldValue, V newValue) {
            synchronized (mutex) {return m.replace(key, oldValue, newValue);}
        }
        @Override
        public V replace(K key, V value) {
            synchronized (mutex) {return m.replace(key, value);}
        }
        @Override
        public V computeIfAbsent(K key,
                Function<? super K, ? extends V> mappingFunction) {
            synchronized (mutex) {return m.computeIfAbsent(key, mappingFunction);}
        }
        @Override
        public V computeIfPresent(K key,
                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
            synchronized (mutex) {return m.computeIfPresent(key, remappingFunction);}
        }
        @Override
        public V compute(K key,
                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
            synchronized (mutex) {return m.compute(key, remappingFunction);}
        }
        @Override
        public V merge(K key, V value,
                BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
            synchronized (mutex) {return m.merge(key, value, remappingFunction);}
        }

        private void writeObject(ObjectOutputStream s) throws IOException {
            synchronized (mutex) {s.defaultWriteObject();}
        }
    }

SynchronizedMapइनपुट Mapऑब्जेक्ट की प्राथमिक विधि में एकल लॉक जोड़ने के रूप में संक्षेप में क्या किया जा सकता है । एक ही समय में कई थ्रेड्स द्वारा लॉक द्वारा संरक्षित सभी विधि तक पहुँचा नहीं जा सकता है। इसका मतलब है कि सामान्य ऑपरेशन जैसे putऔर getसभी डेटा के लिए एक ही समय में एक ही थ्रेड द्वारा निष्पादित किया जा सकता हैMap ऑब्जेक्ट ।

यह बनाता है Map ऑब्जेक्ट थ्रेड को सुरक्षित लेकिन प्रदर्शन कुछ परिदृश्यों में एक मुद्दा बन सकता है।

ConcurrentMapकहीं अधिक कार्यान्वयन में जटिल है, हम उल्लेख कर सकते हैं एक बेहतर HashMap बिल्डिंग जानकारी के लिए। संक्षेप में, यह थ्रेड को सुरक्षित और प्रदर्शन दोनों को ध्यान में रखते हुए लागू किया गया है।

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