mutex และ semaphore ใน Java คืออะไร? อะไรคือความแตกต่างที่สำคัญ?
mutex และ semaphore ใน Java คืออะไร? อะไรคือความแตกต่างที่สำคัญ?
คำตอบ:
สามารถนับเซมาฟอร์ได้ในขณะที่ mutex สามารถนับเป็น 1 เท่านั้น
สมมติว่าคุณมีเธรดที่ทำงานอยู่ซึ่งยอมรับการเชื่อมต่อไคลเอ็นต์ เธรดนี้สามารถรองรับไคลเอนต์ 10 รายพร้อมกัน จากนั้นไคลเอ็นต์ใหม่แต่ละรายจะตั้งค่าสัญญาณจนกว่าจะถึง 10 เมื่อ Semaphore มีแฟล็ก 10 รายการเธรดของคุณจะไม่ยอมรับการเชื่อมต่อใหม่
Mutex มักใช้สำหรับป้องกันสิ่งของ สมมติว่าลูกค้า 10 รายของคุณสามารถเข้าถึงหลายส่วนของระบบได้ จากนั้นคุณสามารถป้องกันส่วนหนึ่งของระบบด้วย mutex ดังนั้นเมื่อ 1 ไคลเอนต์เชื่อมต่อกับระบบย่อยนั้นจะไม่มีใครสามารถเข้าถึงได้ คุณสามารถใช้ Semaphore เพื่อจุดประสงค์นี้ได้เช่นกัน mutex เป็น"การยกเว้นรวมสัญญาณ"
ReentrantLock
. ทั้งหมดนี้เป็นแบบวนซ้ำ ฉันไม่ทราบถึงตัวอย่าง "ในโลกแห่งความจริง" ใด ๆ ของ mutexes ที่ไม่เรียกซ้ำ (ฉันเคยเห็นในหนังสือเรียนเท่านั้น) ดังนั้นฉันจึงไม่ได้พิจารณา
น่าเสียดายที่ทุกคนพลาดความแตกต่างที่สำคัญที่สุดระหว่างสัญญาณและมิวเท็กซ์ แนวคิดเรื่อง " ความเป็นเจ้าของ "
Semaphores ไม่มีแนวคิดในการเป็นเจ้าของซึ่งหมายความว่าเธรดใด ๆ สามารถปลดปล่อยเซมาฟอร์ได้ (ซึ่งอาจนำไปสู่ปัญหามากมายในตัวมันเอง แต่สามารถช่วยในการ "ตรวจจับการตาย") ในขณะที่ mutex มีแนวคิดในการเป็นเจ้าของ (กล่าวคือคุณสามารถปล่อย mutex ที่คุณได้มาเท่านั้น)
ความเป็นเจ้าของเป็นสิ่งสำคัญอย่างยิ่งสำหรับการเขียนโปรแกรมระบบที่ทำงานพร้อมกันอย่างปลอดภัย ฉันมักจะแนะนำให้ใช้ mutex ในการตั้งค่าเซมาฟอร์ (แต่มีผลกระทบด้านประสิทธิภาพ)
นอกจากนี้ Mutexes อาจรองรับการสืบทอดลำดับความสำคัญ (ซึ่งสามารถช่วยแก้ปัญหาการผกผันลำดับความสำคัญ) และการเรียกซ้ำ (กำจัดการหยุดชะงักประเภทหนึ่ง)
นอกจากนี้ควรระบุด้วยว่ามีเซมาโฟร์ "ไบนารี" และเซมาโฟร์ "การนับ / ทั่วไป" เซมาฟอร์ของ Java เป็นเซมาฟอร์สำหรับการนับและทำให้สามารถเริ่มต้นด้วยค่าที่มากกว่าหนึ่ง (ในขณะที่ระบุไว้ว่า mutex สามารถนับตามแนวคิดได้เพียงหนึ่งค่าเท่านั้น) ประโยชน์ของสิ่งนี้ถูกชี้ให้เห็นในโพสต์อื่น ๆ
ดังนั้นเพื่อสรุปเว้นแต่คุณจะมีทรัพยากรมากมายให้จัดการฉันขอแนะนำ mutex เหนือเซมาฟอร์เสมอ
Mutex เป็นการกีดกันซึ่งกันและกันโดยทั่วไป เธรดเดียวเท่านั้นที่สามารถรับทรัพยากรได้ในครั้งเดียว เมื่อเธรดหนึ่งได้รับรีซอร์สจะไม่อนุญาตให้เธรดอื่นรับรีซอร์สจนกว่าเธรดที่เป็นเจ้าของรีซอร์สรีลีส เธรดทั้งหมดที่รอการรับทรัพยากรจะถูกบล็อก
Semaphore ใช้เพื่อควบคุมจำนวนเธรดที่ดำเนินการ จะมีชุดทรัพยากรที่แน่นอน จำนวนทรัพยากรจะลดลงทุกครั้งเมื่อเธรดเป็นเจ้าของเดียวกัน เมื่อจำนวนเซมาฟอร์ถึง 0 จะไม่อนุญาตให้เธรดอื่นได้รับทรัพยากร เธรดถูกบล็อกจนกว่าเธรดอื่นที่เป็นเจ้าของรีลีสรีซอร์ส
ในระยะสั้นความแตกต่างที่สำคัญคือจำนวนเธรดที่ได้รับอนุญาตให้รับทรัพยากรในครั้งเดียว?
mutex ใช้สำหรับการเข้าถึงทรัพยากรแบบอนุกรมในขณะที่สัญญาณ จำกัด การเข้าถึงทรัพยากรถึงจำนวนที่กำหนด คุณสามารถคิดว่า mutex เป็นเซมาฟอร์ที่มีจำนวนการเข้าถึงเป็น 1 ไม่ว่าคุณจะตั้งค่าจำนวนเซมาฟอร์ของคุณเป็นเท่าใดเธรดอาจเข้าถึงทรัพยากรได้ก่อนที่ทรัพยากรจะถูกบล็อก
สัญญาณเป็นกลไกการซิงโครไนซ์การนับ แต่ mutex ไม่ใช่
mutex มักรู้จักกันในชื่อ binary semaphore ในขณะที่เซมาฟอร์สามารถสร้างขึ้นโดยมีการนับที่ไม่ใช่ศูนย์ใด ๆ แต่มิวเทกซ์เป็นคอนเซ็ปต์ฟอร์ที่มีจำนวนบนเป็น 1
คำถามนี้มีคำตอบที่เกี่ยวข้องและลิงก์ไปยังคำแนะนำ Java อย่างเป็นทางการ: มี Mutex ใน Java หรือไม่
สัญญาณ :
สัญญาณการนับ ตามแนวคิดแล้วเซมาฟอร์จะรักษาชุดของใบอนุญาต แต่ละ
acquire()
บล็อกถ้าจำเป็นจนกว่าจะมีใบอนุญาตแล้วจึงรับ แต่ละคนrelease()
เพิ่มใบอนุญาตซึ่งอาจปล่อยผู้ได้รับการบล็อก อย่างไรก็ตามไม่มีการใช้วัตถุอนุญาตจริง Semaphore เพียงแค่นับจำนวนที่มีอยู่และดำเนินการตามนั้น
Semaphores มักใช้เพื่อ จำกัด จำนวนเธรดเกินกว่าที่จะเข้าถึงทรัพยากรบางอย่าง (ฟิสิคัลหรือตรรกะ) ได้
Java ไม่มี Mutex API ในตัว แต่สามารถใช้เป็นสัญญาณไบนารีได้
สัญญาณเริ่มต้นเป็นหนึ่งและใช้ในลักษณะที่มีเพียงหนึ่งใบอนุญาตเท่านั้นที่สามารถใช้เป็นตัวล็อกการยกเว้นร่วมกันได้ สิ่งนี้เรียกกันทั่วไปว่าเซมาฟอร์ไบนารีเนื่องจากมีเพียงสองสถานะ: หนึ่งใบอนุญาตพร้อมใช้งานหรืออนุญาตเป็นศูนย์
เมื่อนำมาใช้ในลักษณะนี้สัญญาณไบนารีมีคุณสมบัติ (ซึ่งแตกต่างจากการใช้งานล็อคอีกหลายคน) ที่ว่า "ล็อค" จะถูกปล่อยออกจากหัวข้ออื่นที่ไม่ใช่เจ้าของ (เป็นสัญญาณมีความคิดของการเป็นเจ้าของไม่ได้) สิ่งนี้มีประโยชน์ในบริบทพิเศษบางอย่างเช่นการกู้คืนการหยุดชะงัก
ดังนั้นความแตกต่างที่สำคัญระหว่าง Semaphore และ Mutex:
Semaphore จำกัด จำนวนเธรดในการเข้าถึงทรัพยากรที่อนุญาต Mutex อนุญาตให้เธรดเดียวเท่านั้นที่สามารถเข้าถึงทรัพยากรได้
ไม่มีเธรดที่เป็นเจ้าของ Semaphore เธรดสามารถอัปเดตจำนวนใบอนุญาตได้โดยการโทรacquire()
และrelease()
วิธีการ Mutexes ควรปลดล็อกโดยเธรดที่ล็อคไว้เท่านั้น
เมื่อใช้ mutex กับตัวแปรเงื่อนไขจะมีการถ่ายคร่อมโดยนัย - เป็นที่ชัดเจนว่าส่วนใดของโปรแกรมถูกปกป้องง. ไม่จำเป็นต้องเป็นกรณีนี้สำหรับเซมาฟอร์ซึ่งอาจเรียกได้ว่าเป็นการไปของการเขียนโปรแกรมพร้อมกัน - มีประสิทธิภาพ แต่ใช้งานง่ายเกินไปในวิธีที่ไม่มีโครงสร้างและไม่แน่นอน
Mutex เป็นเซมาฟอร์ไบนารี ต้องเริ่มต้นด้วย 1 เพื่อให้เป็นไปตามหลักการ First Come First Serve นี้จะทำให้เราไปที่อื่น ๆ คุณสมบัติพิเศษของแต่ละ mutex: คนที่ไม่ลงต้องเป็นคนที่ไม่ขึ้น Ergo เราได้รับการยกเว้นซึ่งกันและกันในทรัพยากรบางอย่าง
ตอนนี้คุณจะเห็นแล้วว่า mutex เป็นกรณีพิเศษของสัญญาณทั่วไป
วัตถุของการซิงโครไนซ์เซมาฟอร์ติดตั้งสัญญาณไฟจราจรแบบคลาสสิก สัญญาณไฟจราจรควบคุมการเข้าถึงทรัพยากรที่ใช้ร่วมกันโดยเคาน์เตอร์ ถ้าตัวนับมากกว่าศูนย์จะได้รับสิทธิ์การเข้าถึง หากเป็นศูนย์การเข้าถึงจะถูกปฏิเสธ ตัวนับจะนับสิทธิ์ที่อนุญาตให้เข้าถึงทรัพยากรที่แชร์ จากนั้นในการเข้าถึงทรัพยากรเธรดจะต้องได้รับอนุญาตจากสัญญาณไฟจราจร โดยทั่วไปในการใช้สัญญาณไฟจราจรเธรดที่ต้องการเข้าถึงทรัพยากรที่แชร์จะพยายามขอใบอนุญาต หากจำนวนสัญญาณไฟจราจรมากกว่าศูนย์เธรดจะได้รับใบอนุญาตและจำนวนสัญญาณไฟจราจรจะลดลง มิฉะนั้นเธรดจะถูกล็อกจนกว่าจะได้รับอนุญาต เมื่อเธรดไม่จำเป็นต้องเข้าถึงรีซอร์สที่แชร์อีกต่อไปเธรดจะปล่อยสิทธิ์ดังนั้นจำนวนสัญญาณไฟจราจรจึงเพิ่มขึ้น หากมีเธรดอื่นที่รอการอนุญาต ได้รับใบอนุญาตในเวลานั้น คลาส Semaphore ของ Java ใช้กลไกนี้
Semaphore มีผู้สร้างสองคน:
Semaphore(int num)
Semaphore(int num, boolean come)
numระบุจำนวนเริ่มต้นของใบอนุญาต จากนั้น num ระบุจำนวนเธรดที่สามารถเข้าถึงทรัพยากรที่ใช้ร่วมกันในเวลาที่กำหนด หาก num เป็นหนึ่งก็สามารถเข้าถึงทรัพยากรได้ทีละเธรด โดยการตั้งค่ามาเป็นจริงคุณสามารถรับประกันได้ว่าหัวข้อที่คุณกำลังรอจะได้รับอนุญาตในการสั่งซื้อที่พวกเขาได้รับการร้องขอ
คุณเปรียบเทียบสิ่งที่หาที่เปรียบไม่ได้ในทางเทคนิคไม่มีความแตกต่างระหว่าง Semaphore และ mutex ซึ่งไม่สมเหตุสมผล Mutex เป็นเพียงชื่อที่มีนัยสำคัญเช่นเดียวกับชื่อใด ๆ ในตรรกะของแอปพลิเคชันหมายความว่าคุณเริ่มต้นเซมาฟอร์ที่ "1" โดยทั่วไปจะใช้เพื่อปกป้องทรัพยากรหรือตัวแปรที่มีการป้องกันเพื่อให้แน่ใจว่ามีการยกเว้นซึ่งกันและกัน