อะไรคือความแตกต่างระหว่างการใช้คลาส wrapper SynchronizedMap
,, a HashMap
และConcurrentHashMap
?
เป็นเพียงความสามารถในการปรับเปลี่ยนในHashMap
ขณะที่ iterating มัน ( ConcurrentHashMap
)?
อะไรคือความแตกต่างระหว่างการใช้คลาส wrapper SynchronizedMap
,, a HashMap
และConcurrentHashMap
?
เป็นเพียงความสามารถในการปรับเปลี่ยนในHashMap
ขณะที่ iterating มัน ( ConcurrentHashMap
)?
คำตอบ:
ซิงโครไนซ์HashMap
:
แต่ละวิธีจะซิงโครไนซ์โดยใช้การล็อกระดับวัตถุ ดังนั้นวิธีการรับและวางบน synchMap จึงได้รับการล็อค
การล็อกคอลเลกชันทั้งหมดเป็นค่าใช้จ่ายด้านประสิทธิภาพ ในขณะที่เธรดหนึ่งล็อกไว้ที่ล็อคไม่มีเธรดอื่นใดสามารถใช้คอลเลกชันได้
ConcurrentHashMap
เปิดตัวใน JDK 5
ไม่มีการล็อคที่ระดับวัตถุการล็อคจะละเอียดยิ่งขึ้น สำหรับ a ConcurrentHashMap
ล็อคอาจอยู่ในระดับที่ฝากข้อมูล hashmap
ผลของการล็อกระดับล่างคือคุณสามารถมีตัวอ่านและตัวเขียนพร้อมกันซึ่งเป็นไปไม่ได้สำหรับคอลเลกชันที่ซิงโครไนซ์ สิ่งนี้นำไปสู่การปรับขนาดได้มากขึ้น
ConcurrentHashMap
ห้ามโยน a ConcurrentModificationException
หากเธรดหนึ่งพยายามแก้ไขขณะที่เธรดอื่นวนซ้ำ
บทความนี้Java 7: HashMap vs ConcurrentHashMap เป็นการอ่านที่ดีมาก แนะนำเป็นอย่างยิ่ง
ConcurrentHashMap
's size()
ผลอาจจะออกจากวันที่ size()
ได้รับอนุญาตให้ส่งคืนค่าประมาณแทนจำนวนที่แน่นอนตามหนังสือ "Java Concurrency in Practice" ดังนั้นวิธีนี้ควรใช้อย่างระมัดระวัง
คำตอบสั้น ๆ :
แผนที่ทั้งสองเป็นการใช้งานMap
ส่วนติดต่อแบบปลอดภัยของเธรด ConcurrentHashMap
ถูกนำมาใช้สำหรับปริมาณงานที่สูงขึ้นในกรณีที่คาดว่าจะเกิดพร้อมกันสูง
บทความของ Brian Goetz เกี่ยวกับแนวคิดที่อยู่เบื้องหลังConcurrentHashMap
เป็นสิ่งที่อ่านได้ดีมาก แนะนำเป็นอย่างยิ่ง
Map m = Collections.synchronizedMap(new HashMap(...));
docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
ConcurrentHashMap
เธรดปลอดภัยโดยไม่ซิงโครไนซ์แผนที่ทั้งหมด การอ่านสามารถเกิดขึ้นได้อย่างรวดเร็วในขณะที่เขียนเสร็จด้วยการล็อก
เราสามารถบรรลุความปลอดภัยของเธรดโดยใช้ทั้ง ConcurrentHashMap และ synchronisedHashmap แต่มีความแตกต่างมากถ้าคุณดูสถาปัตยกรรมของพวกเขา
มันจะรักษาล็อคที่ระดับวัตถุ ดังนั้นหากคุณต้องการดำเนินการใด ๆ เช่นวาง / รับคุณต้องได้รับการล็อคก่อน ในเวลาเดียวกันเธรดอื่นไม่ได้รับอนุญาตให้ดำเนินการใด ๆ ดังนั้นในแต่ละครั้งมีเพียงหนึ่งเธรดเท่านั้นที่สามารถทำงานได้ ดังนั้นเวลาที่รอจะเพิ่มขึ้นที่นี่ เราสามารถพูดได้ว่าประสิทธิภาพค่อนข้างต่ำเมื่อคุณเปรียบเทียบกับ ConcurrentHashMap
มันจะรักษาล็อคที่ระดับเซกเมนต์ มันมี 16 ส่วนและรักษาระดับการทำงานพร้อมกันเป็น 16 โดยค่าเริ่มต้น ดังนั้นในแต่ละครั้งสามารถมี 16 เธรดที่สามารถทำงานบน ConcurrentHashMap ได้ นอกจากนี้การดำเนินการอ่านไม่จำเป็นต้องล็อค ดังนั้นจำนวนเธรดใด ๆ ที่สามารถทำการดำเนินการ get ได้
หาก thread1 ต้องการดำเนินการวางในส่วนที่ 2 และ thread2 ต้องการที่จะดำเนินการใส่ในส่วนที่ 4 แล้วมันได้รับอนุญาตที่นี่ หมายความว่า 16 เธรดสามารถทำการอัปเดต (วาง / ลบ) บน ConcurrentHashMap ได้ตลอดเวลา
ดังนั้นเวลาที่รอจะน้อยกว่าที่นี่ ดังนั้นประสิทธิภาพค่อนข้างดีกว่า synchronizedHashmap
ทั้งคู่เป็นรุ่นที่ใช้งานร่วมกันของ HashMap ซึ่งมีความแตกต่างในการทำงานหลักและโครงสร้างภายในของพวกเขา
ConcurrentHashMapประกอบด้วยส่วนภายในที่สามารถดูเป็นอิสระ HashMaps Conceptually เซกเมนต์ดังกล่าวทั้งหมดสามารถล็อคโดยเธรดแยกต่างหากในการดำเนินการพร้อมกันสูง ดังนั้นหลายเธรดสามารถรับ / วางคู่คีย์ - ค่าจาก ConcurrentHashMap โดยไม่มีการบล็อก / รอกันและกัน สิ่งนี้ถูกนำไปใช้เพื่อปริมาณงานที่สูงขึ้น
แต่ทว่า
Collections.synchronizedMap ()เราได้รับ HashMap เวอร์ชันซิงโครไนซ์และเข้าถึงได้ในลักษณะการบล็อก ซึ่งหมายความว่าหากมีหลายเธรดพยายามเข้าถึง synchronMap ในเวลาเดียวกันพวกเขาจะได้รับอนุญาตให้รับ / ใส่ค่าคีย์คู่ทีละครั้งในลักษณะที่ซิงโครไนซ์
ConcurrentHashMap
ใช้กลไกการล็อคแบบละเอียดยิ่งขึ้นซึ่งเรียกว่าlock stripping
การอนุญาตให้ใช้งานร่วมกันในระดับที่สูงขึ้น เนื่องจากนี้จะให้ดีกว่าที่เห็นพ้องและความยืดหยุ่น
ตัววนซ้ำที่ส่งคืนมาConcurrentHashMap
นั้นมีความสอดคล้องกันอย่างอ่อนช้อยแทนที่จะเป็นเทคนิคที่ล้มเหลวอย่างรวดเร็วซึ่งใช้โดย
วิธีการSynchronizedMap
ระงับการล็อคบนวัตถุในขณะที่ConcurrentHashMap
มีแนวคิดของ "ล็อคสตริป" ที่ล็อคจะถูกเก็บไว้ในถังของเนื้อหาแทน ความยืดหยุ่นและประสิทธิภาพที่เพิ่มขึ้น
ConcurrentHashMap:
1) แผนที่ทั้งคู่เป็นการใช้งานแบบปลอดภัยของเธรดของอินเตอร์เฟสแผนที่
2) ConcurrentHashMap ใช้งานสำหรับปริมาณงานที่สูงขึ้นในกรณีที่คาดว่าจะเกิดภาวะพร้อมกันสูง
3) ไม่มีการล็อคในระดับวัตถุ
แผนที่แฮชตรง:
1) แต่ละวิธีจะซิงโครไนซ์โดยใช้การล็อกระดับวัตถุ
ConcurrentHashMapอนุญาตการเข้าถึงข้อมูลพร้อมกัน แผนที่ทั้งหมดถูกแบ่งออกเป็นส่วน ๆ
อ่านการดำเนินการคือ get(Object key)
ไม่ซิงโครไนซ์แม้ในระดับเซกเมนต์
แต่การดำเนินการเขียนคือ remove(Object key), get(Object key)
ได้รับการล็อคในระดับส่วน มีเพียงบางส่วนของแผนที่ทั้งหมดที่ถูกล็อคเธรดอื่น ๆ ยังคงสามารถอ่านค่าจากส่วนต่าง ๆ ได้ยกเว้นล็อคหนึ่งรายการ
SynchronizedMapในอีกทางได้รับการล็อคที่ระดับวัตถุ เธรดทั้งหมดควรรอเธรดปัจจุบันโดยไม่คำนึงถึงการดำเนินการ (อ่าน / เขียน)
การทดสอบประสิทธิภาพการทำงานที่ง่ายสำหรับ ConcurrentHashMap VS Synchronized
HashMap โฟลว์ทดสอบกำลังเรียกใช้put
ในหนึ่งเธรดและเรียกใช้get
ในสามเธรดMap
พร้อมกัน ดังที่ @trshiv กล่าวว่า ConcurrentHashMap มีปริมาณงานและความเร็วที่สูงขึ้นสำหรับการอ่านที่ไม่มีการล็อก ผลลัพธ์คือเมื่อเวลาในการปฏิบัติงานสิ้นสุดลง10^7
ConcurrentHashMap 2x
เร็วกว่า HashMap ที่ซิงโครไนซ์
SynchronizedMap
และConcurrentHashMap
เป็นทั้งคลาสที่ปลอดภัยของเธรดและสามารถใช้ในแอปพลิเคชันแบบมัลติเธรดความแตกต่างที่สำคัญระหว่างพวกเขาคือเกี่ยวกับวิธีที่พวกเขาบรรลุความปลอดภัยของเธรด
SynchronizedMap
ได้รับการล็อคในอินสแตนซ์แผนที่ทั้งหมดในขณะที่ConcurrentHashMap
แบ่งอินสแตนซ์แผนที่ออกเป็นหลายส่วนและทำการล็อคกับสิ่งเหล่านั้น
ตามเอกสารของ java
Hashtable และ Collections.synchronizedMap (ใหม่ HashMap ()) ถูกซิงโครไนซ์ แต่ ConcurrentHashMap คือ "concurrent"
คอลเลกชันที่เกิดขึ้นพร้อมกันนั้นปลอดภัยต่อเธรด แต่ไม่ได้ควบคุมโดยการล็อคการแยกเดี่ยว
ในกรณีเฉพาะของ ConcurrentHashMap จะอนุญาตการอ่านพร้อมกันจำนวนใด ๆ ได้อย่างปลอดภัยรวมถึงจำนวนที่สามารถปรับแต่งได้ของการเขียนพร้อมกัน คลาส "ที่ซิงโครไนซ์" จะมีประโยชน์เมื่อคุณต้องการป้องกันการเข้าถึงคอลเลกชันทั้งหมดผ่านการล็อกเพียงครั้งเดียว
ในกรณีอื่นที่คาดว่าจะมีหลายเธรดในการเข้าถึงคอลเล็กชันทั่วไป "รุ่นที่เกิดขึ้นพร้อมกัน" จะเป็นที่นิยมกว่า และคอลเลกชันที่ไม่ซิงโครไนซ์จะดีกว่าเมื่อคอลเลกชันใดไม่ได้แชร์หรือสามารถเข้าถึงได้ก็ต่อเมื่อมีการล็อคอื่น ๆ
Hashtable
และSynchronized HashMap
?