mutex และ semaphore ใน Java คืออะไร? อะไรคือความแตกต่างที่สำคัญ?


คำตอบ:


115

สามารถนับเซมาฟอร์ได้ในขณะที่ mutex สามารถนับเป็น 1 เท่านั้น

สมมติว่าคุณมีเธรดที่ทำงานอยู่ซึ่งยอมรับการเชื่อมต่อไคลเอ็นต์ เธรดนี้สามารถรองรับไคลเอนต์ 10 รายพร้อมกัน จากนั้นไคลเอ็นต์ใหม่แต่ละรายจะตั้งค่าสัญญาณจนกว่าจะถึง 10 เมื่อ Semaphore มีแฟล็ก 10 รายการเธรดของคุณจะไม่ยอมรับการเชื่อมต่อใหม่

Mutex มักใช้สำหรับป้องกันสิ่งของ สมมติว่าลูกค้า 10 รายของคุณสามารถเข้าถึงหลายส่วนของระบบได้ จากนั้นคุณสามารถป้องกันส่วนหนึ่งของระบบด้วย mutex ดังนั้นเมื่อ 1 ไคลเอนต์เชื่อมต่อกับระบบย่อยนั้นจะไม่มีใครสามารถเข้าถึงได้ คุณสามารถใช้ Semaphore เพื่อจุดประสงค์นี้ได้เช่นกัน mutex เป็น"การยกเว้นรวมสัญญาณ"


4
นี่ไม่เป็นความจริงเสียทีเดียว เธรดเดียวกันสามารถป้อน mutex เดียวกันได้มากกว่าหนึ่งครั้งดังนั้นจึงต้องมีการนับจำนวนเพื่อให้แน่ใจว่ารายการ & ออกมีความสมดุล
finnw

1
@finnw โดยทั่วไปมีสองประเภทของ mutexes คือเรียกซ้ำและไม่เรียกซ้ำ โดยค่าเริ่มต้น Java ใช้ชนิดเรียกซ้ำหรือไม่
edA-qa mort-ora-y

2
@ edA-qa mort-ora-y คำว่า "Mutex" ไม่ได้ใช้ในข้อมูลจำเพาะ Java VM หรือ API ดังนั้นฉันจึงคิดว่ามันหมายถึงจอภาพที่สร้างขึ้นในทุกวัตถุซึ่งคล้ายกับวัตถุ Win32 ที่เรียกว่า Mutex . เช่นเดียวกับไฟล์ReentrantLock. ทั้งหมดนี้เป็นแบบวนซ้ำ ฉันไม่ทราบถึงตัวอย่าง "ในโลกแห่งความจริง" ใด ๆ ของ mutexes ที่ไม่เรียกซ้ำ (ฉันเคยเห็นในหนังสือเรียนเท่านั้น) ดังนั้นฉันจึงไม่ได้พิจารณา
finnw

2
mutexes แบบไม่เรียกซ้ำสามารถใช้งานได้โดยใช้ Semaphore ด้วยการนับหนึ่ง สิ่งนี้จะมีประโยชน์หากคุณต้องการป้องกันการโทรซ้ำ สิ่งนี้มีการใช้งานจริงฉันใช้มันเป็นการส่วนตัวในโครงการใหญ่เพื่อตรวจจับลูปในรหัสเริ่มต้น (A เริ่มต้น B ซึ่งพยายามเริ่มต้น A อีกครั้ง)
Alexander Torstling

1
ในมาตรฐาน C ++ 11 (C ++ 0x) mutex จะไม่เกิดซ้ำ นอกจากนี้ยังมี 'recursive_mutex' แยกต่างหากสำหรับผู้ที่ต้องการสิ่งนั้น ฉันรู้ว่าเรากำลังพูดถึง Java ที่นี่ แต่ตอนนี้พวกเราหลายคนเขียนโค้ดข้ามภาษา
Aditya Kumar Pandey

139

น่าเสียดายที่ทุกคนพลาดความแตกต่างที่สำคัญที่สุดระหว่างสัญญาณและมิวเท็กซ์ แนวคิดเรื่อง " ความเป็นเจ้าของ "

Semaphores ไม่มีแนวคิดในการเป็นเจ้าของซึ่งหมายความว่าเธรดใด ๆ สามารถปลดปล่อยเซมาฟอร์ได้ (ซึ่งอาจนำไปสู่ปัญหามากมายในตัวมันเอง แต่สามารถช่วยในการ "ตรวจจับการตาย") ในขณะที่ mutex มีแนวคิดในการเป็นเจ้าของ (กล่าวคือคุณสามารถปล่อย mutex ที่คุณได้มาเท่านั้น)
ความเป็นเจ้าของเป็นสิ่งสำคัญอย่างยิ่งสำหรับการเขียนโปรแกรมระบบที่ทำงานพร้อมกันอย่างปลอดภัย ฉันมักจะแนะนำให้ใช้ mutex ในการตั้งค่าเซมาฟอร์ (แต่มีผลกระทบด้านประสิทธิภาพ)

นอกจากนี้ Mutexes อาจรองรับการสืบทอดลำดับความสำคัญ (ซึ่งสามารถช่วยแก้ปัญหาการผกผันลำดับความสำคัญ) และการเรียกซ้ำ (กำจัดการหยุดชะงักประเภทหนึ่ง)

นอกจากนี้ควรระบุด้วยว่ามีเซมาโฟร์ "ไบนารี" และเซมาโฟร์ "การนับ / ทั่วไป" เซมาฟอร์ของ Java เป็นเซมาฟอร์สำหรับการนับและทำให้สามารถเริ่มต้นด้วยค่าที่มากกว่าหนึ่ง (ในขณะที่ระบุไว้ว่า mutex สามารถนับตามแนวคิดได้เพียงหนึ่งค่าเท่านั้น) ประโยชน์ของสิ่งนี้ถูกชี้ให้เห็นในโพสต์อื่น ๆ

ดังนั้นเพื่อสรุปเว้นแต่คุณจะมีทรัพยากรมากมายให้จัดการฉันขอแนะนำ mutex เหนือเซมาฟอร์เสมอ


1
คำตอบของ Feabhas ค่อนข้างสำคัญ - mutex จะตรวจสอบเธรดที่พยายามปล่อย mutex ที่เป็นเจ้าของจริง ฉันมีคำถามนี้เป็นคำถามสัมภาษณ์ดังนั้นจึงควรค่าแก่การพยายามจดจำ
andrew pate

40

Mutex เป็นการกีดกันซึ่งกันและกันโดยทั่วไป เธรดเดียวเท่านั้นที่สามารถรับทรัพยากรได้ในครั้งเดียว เมื่อเธรดหนึ่งได้รับรีซอร์สจะไม่อนุญาตให้เธรดอื่นรับรีซอร์สจนกว่าเธรดที่เป็นเจ้าของรีซอร์สรีลีส เธรดทั้งหมดที่รอการรับทรัพยากรจะถูกบล็อก

Semaphore ใช้เพื่อควบคุมจำนวนเธรดที่ดำเนินการ จะมีชุดทรัพยากรที่แน่นอน จำนวนทรัพยากรจะลดลงทุกครั้งเมื่อเธรดเป็นเจ้าของเดียวกัน เมื่อจำนวนเซมาฟอร์ถึง 0 จะไม่อนุญาตให้เธรดอื่นได้รับทรัพยากร เธรดถูกบล็อกจนกว่าเธรดอื่นที่เป็นเจ้าของรีลีสรีซอร์ส

ในระยะสั้นความแตกต่างที่สำคัญคือจำนวนเธรดที่ได้รับอนุญาตให้รับทรัพยากรในครั้งเดียว?

  • Mutex - เป็นหนึ่ง
  • สัญญาณ - DEFINED_COUNT ของมัน (มากถึงจำนวนเซมาฟอร์)

8

mutex ใช้สำหรับการเข้าถึงทรัพยากรแบบอนุกรมในขณะที่สัญญาณ จำกัด การเข้าถึงทรัพยากรถึงจำนวนที่กำหนด คุณสามารถคิดว่า mutex เป็นเซมาฟอร์ที่มีจำนวนการเข้าถึงเป็น 1 ไม่ว่าคุณจะตั้งค่าจำนวนเซมาฟอร์ของคุณเป็นเท่าใดเธรดอาจเข้าถึงทรัพยากรได้ก่อนที่ทรัพยากรจะถูกบล็อก



3

mutex มักรู้จักกันในชื่อ binary semaphore ในขณะที่เซมาฟอร์สามารถสร้างขึ้นโดยมีการนับที่ไม่ใช่ศูนย์ใด ๆ แต่มิวเทกซ์เป็นคอนเซ็ปต์ฟอร์ที่มีจำนวนบนเป็น 1



1

สัญญาณ :

สัญญาณการนับ ตามแนวคิดแล้วเซมาฟอร์จะรักษาชุดของใบอนุญาต แต่ละacquire()บล็อกถ้าจำเป็นจนกว่าจะมีใบอนุญาตแล้วจึงรับ แต่ละคนrelease()เพิ่มใบอนุญาตซึ่งอาจปล่อยผู้ได้รับการบล็อก อย่างไรก็ตามไม่มีการใช้วัตถุอนุญาตจริง Semaphore เพียงแค่นับจำนวนที่มีอยู่และดำเนินการตามนั้น

Semaphores มักใช้เพื่อ จำกัด จำนวนเธรดเกินกว่าที่จะเข้าถึงทรัพยากรบางอย่าง (ฟิสิคัลหรือตรรกะ) ได้

Java ไม่มี Mutex API ในตัว แต่สามารถใช้เป็นสัญญาณไบนารีได้

สัญญาณเริ่มต้นเป็นหนึ่งและใช้ในลักษณะที่มีเพียงหนึ่งใบอนุญาตเท่านั้นที่สามารถใช้เป็นตัวล็อกการยกเว้นร่วมกันได้ สิ่งนี้เรียกกันทั่วไปว่าเซมาฟอร์ไบนารีเนื่องจากมีเพียงสองสถานะ: หนึ่งใบอนุญาตพร้อมใช้งานหรืออนุญาตเป็นศูนย์

เมื่อนำมาใช้ในลักษณะนี้สัญญาณไบนารีมีคุณสมบัติ (ซึ่งแตกต่างจากการใช้งานล็อคอีกหลายคน) ที่ว่า "ล็อค" จะถูกปล่อยออกจากหัวข้ออื่นที่ไม่ใช่เจ้าของ (เป็นสัญญาณมีความคิดของการเป็นเจ้าของไม่ได้) สิ่งนี้มีประโยชน์ในบริบทพิเศษบางอย่างเช่นการกู้คืนการหยุดชะงัก

ดังนั้นความแตกต่างที่สำคัญระหว่าง Semaphore และ Mutex:

  1. Semaphore จำกัด จำนวนเธรดในการเข้าถึงทรัพยากรที่อนุญาต Mutex อนุญาตให้เธรดเดียวเท่านั้นที่สามารถเข้าถึงทรัพยากรได้

  2. ไม่มีเธรดที่เป็นเจ้าของ Semaphore เธรดสามารถอัปเดตจำนวนใบอนุญาตได้โดยการโทรacquire()และrelease()วิธีการ Mutexes ควรปลดล็อกโดยเธรดที่ล็อคไว้เท่านั้น

  3. เมื่อใช้ mutex กับตัวแปรเงื่อนไขจะมีการถ่ายคร่อมโดยนัย - เป็นที่ชัดเจนว่าส่วนใดของโปรแกรมถูกปกป้องง. ไม่จำเป็นต้องเป็นกรณีนี้สำหรับเซมาฟอร์ซึ่งอาจเรียกได้ว่าเป็นการไปของการเขียนโปรแกรมพร้อมกัน - มีประสิทธิภาพ แต่ใช้งานง่ายเกินไปในวิธีที่ไม่มีโครงสร้างและไม่แน่นอน


0

Mutex เป็นเซมาฟอร์ไบนารี ต้องเริ่มต้นด้วย 1 เพื่อให้เป็นไปตามหลักการ First Come First Serve นี้จะทำให้เราไปที่อื่น ๆ คุณสมบัติพิเศษของแต่ละ mutex: คนที่ไม่ลงต้องเป็นคนที่ไม่ขึ้น Ergo เราได้รับการยกเว้นซึ่งกันและกันในทรัพยากรบางอย่าง

ตอนนี้คุณจะเห็นแล้วว่า mutex เป็นกรณีพิเศษของสัญญาณทั่วไป


0

วัตถุของการซิงโครไนซ์เซมาฟอร์ติดตั้งสัญญาณไฟจราจรแบบคลาสสิก สัญญาณไฟจราจรควบคุมการเข้าถึงทรัพยากรที่ใช้ร่วมกันโดยเคาน์เตอร์ ถ้าตัวนับมากกว่าศูนย์จะได้รับสิทธิ์การเข้าถึง หากเป็นศูนย์การเข้าถึงจะถูกปฏิเสธ ตัวนับจะนับสิทธิ์ที่อนุญาตให้เข้าถึงทรัพยากรที่แชร์ จากนั้นในการเข้าถึงทรัพยากรเธรดจะต้องได้รับอนุญาตจากสัญญาณไฟจราจร โดยทั่วไปในการใช้สัญญาณไฟจราจรเธรดที่ต้องการเข้าถึงทรัพยากรที่แชร์จะพยายามขอใบอนุญาต หากจำนวนสัญญาณไฟจราจรมากกว่าศูนย์เธรดจะได้รับใบอนุญาตและจำนวนสัญญาณไฟจราจรจะลดลง มิฉะนั้นเธรดจะถูกล็อกจนกว่าจะได้รับอนุญาต เมื่อเธรดไม่จำเป็นต้องเข้าถึงรีซอร์สที่แชร์อีกต่อไปเธรดจะปล่อยสิทธิ์ดังนั้นจำนวนสัญญาณไฟจราจรจึงเพิ่มขึ้น หากมีเธรดอื่นที่รอการอนุญาต ได้รับใบอนุญาตในเวลานั้น คลาส Semaphore ของ Java ใช้กลไกนี้

Semaphore มีผู้สร้างสองคน:

Semaphore(int num)
Semaphore(int num, boolean come)

numระบุจำนวนเริ่มต้นของใบอนุญาต จากนั้น num ระบุจำนวนเธรดที่สามารถเข้าถึงทรัพยากรที่ใช้ร่วมกันในเวลาที่กำหนด หาก num เป็นหนึ่งก็สามารถเข้าถึงทรัพยากรได้ทีละเธรด โดยการตั้งค่ามาเป็นจริงคุณสามารถรับประกันได้ว่าหัวข้อที่คุณกำลังรอจะได้รับอนุญาตในการสั่งซื้อที่พวกเขาได้รับการร้องขอ


0

คุณเปรียบเทียบสิ่งที่หาที่เปรียบไม่ได้ในทางเทคนิคไม่มีความแตกต่างระหว่าง Semaphore และ mutex ซึ่งไม่สมเหตุสมผล Mutex เป็นเพียงชื่อที่มีนัยสำคัญเช่นเดียวกับชื่อใด ๆ ในตรรกะของแอปพลิเคชันหมายความว่าคุณเริ่มต้นเซมาฟอร์ที่ "1" โดยทั่วไปจะใช้เพื่อปกป้องทรัพยากรหรือตัวแปรที่มีการป้องกันเพื่อให้แน่ใจว่ามีการยกเว้นซึ่งกันและกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.