ความแตกต่างระหว่างเซมาฟอร์ไบนารีและ mutex


819

มีความแตกต่างระหว่างเซมาฟอร์ไบนารีและ mutex หรือว่าพวกมันเหมือนกันหรือไม่?


11
พวกมันมีความหมายเหมือนกัน แต่ในทางปฏิบัติคุณจะสังเกตเห็นความแตกต่างแปลก ๆ (โดยเฉพาะใน Windows)
Michael Foukarakis

5
@Michael Foukarakis: อะไรคือความแตกต่างที่แปลกประหลาด?
ฟิลิปป์

2
ฉันคิดว่าแปลก ๆ ไม่ใช่การแสดงออกที่ถูกต้อง Mutex ยังสนับสนุนความเป็นเจ้าของและบางครั้งกลับเข้ามาใหม่ นี่เป็นกรณีใน Windows นอกจากนี้ semaphores ใน Windows ถูกนำมาใช้ด้านบนของวัตถุกิจกรรม แต่ฉันไม่แน่ใจเกี่ยวกับผลกระทบเชิงปฏิบัติของสิ่งนี้
Michael Foukarakis

1
การอภิปรายที่คล้ายกันในstackoverflow.com/questions/4039899/…
Karthik Balaguru

2
@philipxy อย่างดีซ่อน 'rn' แทนที่ 'm'
Mooncrater

คำตอบ:


691

พวกเขาไม่เหมือนกัน พวกเขาจะใช้เพื่อวัตถุประสงค์ที่แตกต่างกัน!
ในขณะที่ semaphores ทั้งสองประเภทมีสถานะเต็ม / ว่างเปล่าและใช้ API เดียวกันการใช้งานของพวกเขานั้นแตกต่างกันมาก

Semaphores การ
รวม Mutual Semaphores การรวม Mutual ถูกใช้เพื่อปกป้องทรัพยากรที่ใช้ร่วมกัน (โครงสร้างข้อมูล, ไฟล์, ฯลฯ .. )

เซมาฟอร์ Mutex คือ "เป็นเจ้าของ" โดยงานที่รับได้ หาก Task B พยายามที่จะ semGive mutex ที่จัดขึ้นโดย Task A ในปัจจุบันการเรียก Task B จะส่งคืนข้อผิดพลาดและล้มเหลว

Mutexes ใช้ลำดับต่อไปนี้เสมอ:

  - SemTake
  - มาตราที่สำคัญ
  - SemGive

นี่คือตัวอย่างง่ายๆ:

  เธรด A เธรด B
   รับ Mutex
     เข้าถึงข้อมูล
     ... รับ Mutex <== จะบล็อก
     ...
   ให้ข้อมูลการเข้าถึง Mutex <== เลิกบล็อก
                                  ...
                                ให้ Mutex

เซมาฟอร์แบบไบนารีสัญญาณ
แบบไบนารีที่อยู่คำถามที่แตกต่างกันโดยสิ้นเชิง:

  • ภารกิจ B มักจะรอบางสิ่งบางอย่างเกิดขึ้น (เซ็นเซอร์ถูกสะดุดเช่น)
  • การเดินทางของเซ็นเซอร์และรูทีนการบริการขัดจังหวะทำงาน มันจำเป็นต้องแจ้งภารกิจของการเดินทาง
  • ภารกิจ B ควรดำเนินการและดำเนินการที่เหมาะสมสำหรับการเดินทางของเซ็นเซอร์ จากนั้นกลับไปรอ

   Task A                      Task B
   ...                         Take BinSemaphore   <== wait for something
   Do Something Noteworthy
   Give BinSemaphore           do something    <== unblocks

โปรดทราบว่าด้วยสัญญาณสัญญาณแบบไบนารีมันก็โอเคสำหรับ B ที่จะใช้สัญญาณสัญญาณและ A เพื่อให้มัน
อีกครั้งสัญญาณสัญญาณไบนารีไม่ได้ป้องกันทรัพยากรจากการเข้าถึง การกระทำของการให้และการส่งสัญญาณจะ decoupled พื้นฐาน
โดยทั่วไปแล้วจะไม่มีเหตุผลสำหรับงานเดียวกันดังนั้นการให้และรับสัญญาณเซมาฟอร์ไบนารีเดียวกัน


12
Mutex นั้นดีกว่าเซมาฟอร์ไบนารีหรือไม่? เนื่องจากมันไม่สมเหตุสมผลถ้ามีคนปลดล็อคซึ่งเขาไม่ได้ถืออยู่จริง
Pacerier

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

5
@Pacerier คุณสับสนกับวัตถุประสงค์ Mutex มีไว้เพื่อปกป้องภูมิภาคที่สำคัญ คุณถูกต้องมันไม่มีเหตุผลที่จะใช้ Binary Semaphore ฉันจะอัปเดตคำตอบเพื่ออธิบายวัตถุประสงค์ของแต่ละข้อ
เบอนัวต์

4
@Benoit ดังนั้นเราสามารถพูดได้ว่า Mutex ใช้สำหรับอะตอมมิกและ Binary Semaphore สำหรับมุมมองการสั่งซื้อเนื่องจากภารกิจ B จะรอ Task A เพื่อส่งสัญญาณการปลดล็อคโดยเนื้อแท้
abhi

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

446
  • mutexสามารถได้รับการปล่อยตัวโดยเฉพาะหัวข้อที่ได้ซื้อมา
  • สัญญาณไบนารีสามารถส่งสัญญาณโดยด้ายใด ๆ (หรือกระบวนการ)

ดังนั้นเซมาฟอร์จึงเหมาะสมกว่าสำหรับปัญหาการซิงโครไนซ์บางอย่างเช่น

บน Windows semaphores ไบนารีเป็นเหมือนวัตถุเหตุการณ์มากกว่า mutexes


34
Mutex can be released only by thread that had acquired it- ฉันเพิ่งลองกับโปรแกรมที่ใช้ pthread_mutex อย่างง่ายเธรดสามารถปลดล็อก mutex ที่ถูกล็อกในเธรดหลักได้
daisy

15
@ warl0ck ตามหน้า man ของ pthread_mutex_lock linux.die.net/man/3/pthread_mutex_lock : "ถ้าประเภท mutex เป็น PTHREAD_MUTEX_ERRORCHECK เธรดการตรวจสอบข้อผิดพลาดจะต้องได้รับ .... ถ้าเธรดพยายามปลดล็อก mutex ที่มีอยู่ ไม่ล็อคหรือ mutex ที่ปลดล็อคข้อผิดพลาดจะถูกส่งกลับ "
amit

47
@ warl0ck โปรดดูstackoverflow.com/a/5492499/385064 'Pthreads มี mutexes 3 ชนิด: mutex อย่างรวดเร็ว, mutex แบบเรียกซ้ำและการตรวจสอบข้อผิดพลาด mutex คุณใช้ mutex ที่รวดเร็วซึ่งด้วยเหตุผลด้านประสิทธิภาพจะไม่ตรวจสอบข้อผิดพลาดนี้ หากคุณใช้ข้อผิดพลาดในการตรวจสอบ mutex บน Linux คุณจะพบผลลัพธ์ที่คุณคาดหวัง '
FrostNovaZzz

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

1
@achoora ฉันยอมรับว่ามันเป็นสิ่งที่ผิดที่จะเชี่ยวชาญสัญญาณในการประสาน จริงๆแล้ว mutex, binary-semaphore, barrier, pipelines นั้นมีรูปแบบที่แตกต่างกันสำหรับการซิงโครไนซ์ ในมุมมองการออกแบบ mutex เป็นเหมือนรูปแบบสถานะซึ่งอัลกอริทึมที่เลือกโดยรัฐสามารถเปลี่ยนสถานะได้ ไบนารี - สัญญาณเป็นเหมือนรูปแบบกลยุทธ์ที่อัลกอริทึมภายนอกสามารถเปลี่ยนสถานะและในที่สุดอัลกอริทึม / กลยุทธ์ที่เลือกให้ทำงาน
shuva

442

ตัวอย่างห้องน้ำเป็นการเปรียบเทียบที่สนุกสนาน:

mutex:

เป็นกุญแจสำคัญในการเข้าห้องน้ำ บุคคลหนึ่งสามารถมีกุญแจ - ครอบครองห้องน้ำ - ในเวลา เมื่อเสร็จแล้วบุคคลจะให้ (ปลดปล่อย) กุญแจแก่บุคคลต่อไปในคิว

อย่างเป็นทางการ: "โดยทั่วไปแล้ว Mutex จะถูกใช้เพื่อทำให้การเข้าถึงส่วนของรหัสผู้เข้าร่วมใหม่ที่ไม่สามารถดำเนินการพร้อมกันโดยมากกว่าหนึ่งเธรดได้พร้อมกันมากกว่าหนึ่งเธรด Mutex วัตถุอนุญาตให้เธรดหนึ่งเข้าไปในส่วนควบคุมบังคับให้เธรดอื่นที่พยายามเข้าถึง ส่วนนั้นจะรอจนกว่าเธรดแรกจะออกจากส่วนนั้น " Ref: Symbian Developer Library

(mutex เป็นเซมาฟอร์ที่มีค่า 1)

สัญญาณ:

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

อย่างเป็นทางการ: "เซมาฟอร์ จำกัด จำนวนผู้ใช้พร้อมกันของทรัพยากรที่ใช้ร่วมกันถึงจำนวนสูงสุดเธรดสามารถร้องขอการเข้าถึงทรัพยากร (ลดเซมาฟอร์) และสามารถส่งสัญญาณว่าพวกเขาเสร็จสิ้นการใช้ทรัพยากร (เพิ่มเซมาฟอร์) " Ref: Symbian Developer Library


234
... แต่นี่เป็นเรื่องของ mutex กับการนับเซมาฟอร์ คำถามที่ถูกถามเกี่ยวกับไบนารี
Roman Nikitchenko

24
ในขณะที่สิ่งที่ดาวิดพูดนั้นถูกต้อง แต่ก็ไม่ใช่คำตอบของคำถามที่ถาม คำตอบ Mladen Jankovic คือคำตอบของคำถามที่ถามซึ่งมีจุดใดบ้างที่ทำให้แยกความแตกต่าง "binary-semaphore" กับ "mutex"
Ajeet Ganga

13
น่าเสียดายที่คำตอบที่ไม่ถูกต้องนี้มีคะแนนมากกว่าคำตอบที่ดีที่สุดโดย @Benoit
NeonGlow

6
คำตอบนี้ทำให้เข้าใจผิดคุณควรเปรียบเทียบกับ Binary Semaphore เท่านั้น
Hemanth

3
สิ่งนี้ยังแสดงให้เห็นถึงปัญหาในการใช้เซมาฟอร์นับเพื่อปกป้องทรัพยากรที่ใช้ร่วมกัน: หากคีย์เหมือนกันจริง ๆ และส้วมถูกปลดล็อคโดยใช้กุญแจและไม่มีกลไกอื่น ๆ ที่จะกระจายการใช้งานกุฏิ ผู้ใช้ปลดล็อคเข้าสู่และเริ่มใช้กุฏิแรก (2) ผู้ใช้คนถัดไปปลดล็อคเข้าและเริ่มใช้กุฏิแรก ...
Technophile

151

บทความที่ดีในหัวข้อ:

จากส่วนที่ 2:

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


ขอบคุณสำหรับลิงค์คำอธิบายที่ยอดเยี่ยม ลิงค์มีการเปลี่ยนแปลง: feabhas.com/blog/2009/09/… (ใช้ <ก่อนหน้าและถัดไป> เพื่อนำทางไปยังบทความอีกสองบทความ
Aaron H.

@ Aaron ฉันแก้ไขลิงก์
ผู้พิพากษา Maygarden

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

1
+1 ลิงก์บทความที่ยอดเยี่ยมของศัตรู บทความที่ดีที่สุดที่อธิบายเซมาฟอร์และ mutex ด้วย "what-it-is" และ "what-it-do" computing.llnl.gov/tutorials/pthreadsฉันใช้บทความนี้เป็นการอ้างอิงเบื้องหลังซึ่งเป็นเทคนิคที่อธิบายทุกอย่างเกี่ยวกับ mutex / conditionals และโครงสร้างอื่น ๆ ที่สร้างอยู่ด้านบนเช่นเซมาฟอร์ / สิ่งกีดขวาง / เครื่องอ่าน - ผู้เขียน แต่ไม่มีที่ไหนชัดเจนและรัดกุมเกี่ยวกับปัญหาที่ต้องเผชิญกับการสร้าง ในระยะสั้นมันคือการอ้างอิง :)
Ajeet Ganga

เข้าใจง่ายกว่าคำตอบอื่น ๆ
BinaryTreeee

101

เนื่องจากคำตอบข้างต้นไม่ได้เป็นการขจัดความสับสนนี่คือสิ่งที่ทำให้ฉันสับสน

พูดอย่างเคร่งครัดmutex เป็นกลไกการล็อคที่ใช้ในการประสานการเข้าถึงทรัพยากร งานเดียวเท่านั้น (สามารถเป็นเธรดหรือกระบวนการที่อยู่บนพื้นฐานของ OS นามธรรม) สามารถรับ mutex หมายความว่าจะมีความเป็นเจ้าของที่เกี่ยวข้องกับ mutex และมีเพียงเจ้าของเท่านั้นที่สามารถปลดล็อค (mutex)

สัญญาณคือกลไกการส่งสัญญาณ (“ ฉันเสร็จแล้วคุณสามารถดำเนินการต่อ” สัญญาณชนิด) ตัวอย่างเช่นหากคุณกำลังฟังเพลง (ถือว่าเป็นงานเดียว) บนมือถือของคุณและในเวลาเดียวกันที่เพื่อนของคุณโทรหาคุณอินเทอรัปต์จะถูกเรียกตามที่รูทีนการบริการขัดจังหวะ (ISR) จะส่งสัญญาณให้งานประมวลผลการโทร .

ที่มา: http://www.geeksforgeeks.org/mutex-vs-semaphore/


42

ความหมายการซิงโครไนซ์ของพวกเขาแตกต่างกันมาก:

  • mutexes อนุญาตให้ซีเรียลไลซ์เซชันของการเข้าถึงรีซอร์สที่กำหนดเช่นหลายเธรดรอการล็อกทีละหนึ่งและตามที่กล่าวไว้ก่อนหน้าเธรดจะเป็นเจ้าของการล็อกจนกว่าจะเสร็จสิ้น: เท่านั้นเฉพาะเธรดเฉพาะนี้สามารถปลดล็อกได้
  • สัญญาณแบบไบนารีคือตัวนับที่มีค่า 0 และ 1: งานบล็อกบนมันจนกว่างานใด ๆจะ sem_post สัญญาณส่งสัญญาณโฆษณาว่าทรัพยากรพร้อมใช้งานและจัดเตรียมกลไกเพื่อรอจนกว่าจะมีการส่งสัญญาณว่าพร้อมใช้งานแล้ว

เช่นนี้สามารถดู mutex เป็นโทเค็นที่ส่งจากงานไปยังงานและสัญญาณที่เป็นแสงสีแดงการจราจร (มันสัญญาณคนที่สามารถดำเนินการต่อ)


23

ในระดับทฤษฎีพวกเขาจะไม่แตกต่างกันทางความหมาย คุณสามารถใช้ mutex โดยใช้ semaphores หรือในทางกลับกัน (ดูตัวอย่างที่นี่ ) ในทางปฏิบัติการนำไปใช้นั้นแตกต่างกันและให้บริการต่างกันเล็กน้อย

ความแตกต่างในทางปฏิบัติ (ในแง่ของการบริการของระบบที่อยู่รอบตัวพวกเขา) คือการดำเนินการของ mutex มีวัตถุประสงค์เพื่อเป็นกลไกการซิงโครไนซ์ที่มีน้ำหนักเบากว่า ใน oracle-speak นั้น mutexes นั้นรู้จักกันในชื่อlatchesและ semaphores นั้นรู้จักกันในชื่อwaitsรอ

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

การประยุกต์ใช้ mutex ทั่วไปมีกระบวนการหรือเธรดที่ดำเนินการคำสั่งทดสอบและตั้งค่าและประเมินว่ามีสิ่งอื่นใดที่ตั้งค่า mutex จุดสำคัญที่นี่คือว่าไม่มีการโต้ตอบกับตัวจัดตารางเวลาดังนั้นเราจึงไม่มีความคิด (และไม่สนใจ) ที่ตั้งค่าการล็อก จากนั้นเราทั้งให้ขึ้นชิ้นเวลาของเราและความพยายามอีกครั้งเมื่อมีงานเป็นอีกครั้งที่กำหนดหรือดำเนินการหมุนล็อค Spin lock เป็นอัลกอริทึมเช่น:

Count down from 5000:
     i. Execute the test-and-set instruction
    ii. If the mutex is clear, we have acquired it in the previous instruction 
        so we can exit the loop
   iii. When we get to zero, give up our time slice.

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

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

อัลกอริทึมสัญญาณเบื้องต้นดูเหมือนว่า:

(somewhere in the program startup)
Initialise the semaphore to its start-up value.

Acquiring a semaphore
   i. (synchronised) Attempt to decrement the semaphore value
  ii. If the value would be less than zero, put the task on the tail of the list of tasks waiting on the semaphore and give up the time slice.

Posting a semaphore
   i. (synchronised) Increment the semaphore value
  ii. If the value is greater or equal to the amount requested in the post at the front of the queue, take that task off the queue and make it runnable.  
 iii. Repeat (ii) for all tasks until the posted value is exhausted or there are no more tasks waiting.

ในกรณีของสัญญาณเซมาฟอร์ความแตกต่างในทางปฏิบัติที่สำคัญระหว่างสองคือลักษณะของบริการระบบโดยรอบโครงสร้างข้อมูลจริง

แก้ไข: ตามที่ evan ได้ชี้ให้เห็นอย่างถูกต้อง spinlocks จะชะลอตัวลงเครื่องประมวลผลเดียว คุณจะใช้ spinlock ในกล่องตัวประมวลผลหลายตัวเท่านั้นเพราะในโปรเซสเซอร์เดียวกระบวนการที่ถือ mutex จะไม่รีเซ็ตในขณะที่งานอื่นกำลังทำงานอยู่ Spinlocks มีประโยชน์เฉพาะในสถาปัตยกรรมแบบมัลติโปรเซสเซอร์


1
ฉันไม่คิดว่ามันเป็นเรื่องธรรมดาสำหรับ mutex ที่จะนำไปใช้กับ spinlock บนเครื่อง Uni-proc มันจะแย่มากสำหรับประสิทธิภาพ
Evan Teran

โดยปกติคุณจะใช้ spinlock ในระบบมัลติโปรเซสเซอร์เท่านั้น
ConcOfOfTunbridgeWells

แม้แต่ใน SMP หลังจากปั่นไปสองสามครั้งคุณก็กลับไปสู่โหมดสลีป / ปลุกที่ใช้ระบบปฏิบัติการได้ (เช่นมีการfutexเรียกใช้ระบบLinux เพื่อช่วยให้การติดตั้ง userspace mutex / semaphore ที่มีเวลาแฝงต่ำ. en.wikipedia.org/wiki/Futex ) ในเส้นทางที่ไม่มีการโต้แย้งอย่างรวดเร็วหรือหากทรัพยากรพร้อมใช้งานเร็ว ๆ นี้คุณจะไม่มีค่าใช้จ่าย การเรียกระบบ แต่คุณจะไม่ใช้เวลามากกว่าสองสามวินาทีในการรอคอย (หมุน) การปรับพารามิเตอร์ของการหมุนวนย้อนกลับและรอเป็นฮาร์ดแวร์และปริมาณงานที่แน่นอน แต่ไลบรารีมาตรฐานมักจะมีตัวเลือกที่เหมาะสม
Peter Cordes

19

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


"สามารถส่งสัญญาณโดยเธรดอื่น" มันหมายถึงอะไรให้เป็นตัวอย่าง
Myanju

15

Mutex: สมมติว่าเรามีเธรดส่วนที่สำคัญ T1 ต้องการเข้าถึงจากนั้นทำตามขั้นตอนด้านล่าง T1:

  1. ล็อค
  2. ใช้ส่วนที่สำคัญ
  3. ปลดล็อค

สัญญาณสัญญาณแบบไบนารี: ทำงานตามการรอสัญญาณและสัญญาณ การรอลดค่า "s" โดยปกติค่า "s" จะเริ่มต้นด้วยค่า "1" สัญญาณจะเพิ่มค่า "s" ทีละรายการ ถ้าค่า "s" เป็น 1 หมายถึงไม่มีใครใช้ส่วนที่สำคัญเมื่อค่าเป็น 0 หมายถึงส่วนที่สำคัญกำลังถูกใช้งาน สมมติว่าเธรด T2 กำลังใช้ส่วนที่สำคัญจากนั้นจึงทำตามขั้นตอนด้านล่าง T2:

  1. wait (s) // initial s value คือหนึ่งหลังจากการโทรรอมันมีค่าลดลงโดยหนึ่งเช่น 0
  2. ใช้ส่วนที่สำคัญ
  3. สัญญาณ // ตอนนี้มูลค่าเพิ่มขึ้นและกลายเป็น 1

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


12

บน Windows มีสองความแตกต่างระหว่าง mutexes และ semaphores ไบนารี:

  1. mutex สามารถปล่อยได้โดยเธรดที่มีความเป็นเจ้าของเท่านั้นเช่นเธรดซึ่งก่อนหน้านี้เรียกว่าฟังก์ชัน Wait (หรือที่ใช้ความเป็นเจ้าของเมื่อสร้างมัน) สัญญาณสามารถปล่อยโดยด้ายใด ๆ

  2. เธรดสามารถเรียกใช้ฟังก์ชันการรอซ้ำ ๆ บน mutex โดยไม่มีการบล็อก อย่างไรก็ตามถ้าคุณเรียกใช้ฟังก์ชันการรอสองครั้งในสัญญาณแบบไบนารีโดยไม่ปล่อยสัญญาณในระหว่างเธรดจะบล็อก


4
คำตอบที่ดี. ใน # 2 คุณกำลังอธิบายถึง mutex แบบเรียกซ้ำ - ไม่ใช่ mutex ทั้งหมดที่จำเป็นต้องเรียกซ้ำ เช่นcs.wustl.edu/~schmidt/ACE.FAQ.html#Q14
Dan

10

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

  • ด้วย“ mutex” สิ่งนี้ไม่สามารถเกิดขึ้นได้ ไม่มีเธรดอื่นใดสามารถปลดล็อกการล็อกในเธรดของคุณ
  • ด้วย“ ไบนารีสัญญาณ” นี้สามารถเกิดขึ้นได้ เธรดอื่น ๆ สามารถปลดล็อกการล็อกในเธรดของคุณ

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


10

Mutex ใช้สำหรับ "กลไกการล็อค" ทีละกระบวนการสามารถใช้ทรัพยากรที่ใช้ร่วมกันได้

แต่ทว่า

Semaphores ใช้สำหรับ "กลไกการส่งสัญญาณ" เช่น "ฉันเสร็จแล้วตอนนี้สามารถดำเนินการต่อ"


9

ตำนาน:

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

ประเด็นสำคัญ:

•เธรดสามารถรับการล็อกมากกว่าหนึ่ง (Mutex)

• Mutex สามารถล็อคได้มากกว่าหนึ่งครั้งก็ต่อเมื่อเป็นการเรียกซ้ำ mutex ที่นี่ล็อคและปลดล็อคสำหรับ mutex ควรจะเหมือนกัน

•หากเธรดที่ล็อก mutex ไว้แล้วพยายามล็อก mutex อีกครั้งเธรดนั้นจะเข้าสู่รายการรอของ mutex นั้นซึ่งส่งผลให้เกิดการหยุดชะงัก

•สัญญาณเซมาฟอร์และ mutex คล้ายกัน แต่ไม่เหมือนกัน

Mutex เป็นการดำเนินการที่มีค่าใช้จ่ายสูงเนื่องจากโปรโตคอลการป้องกันที่เกี่ยวข้อง

•เป้าหมายหลักของ mutex คือบรรลุการเข้าถึงอะตอมหรือล็อคทรัพยากร


8

Mutexควบคุมการเข้าถึงทรัพยากรที่ใช้ร่วมกันเพียงครั้งเดียว จะให้การดำเนินงานเพื่อรับ ()การเข้าถึงทรัพยากรนั้นและปล่อย ()เมื่อทำเสร็จแล้ว

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

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

เซมาฟอร์จึงเป็นนามธรรมที่สูงกว่า Mutex Mutex สามารถดำเนินการได้โดยใช้สัญญาณ แต่ไม่ใช่วิธีอื่น ๆ


6

คำถามที่แก้ไขคือ - อะไรคือความแตกต่างระหว่าง A mutex และสัญญาณ "ไบนารี" ใน "Linux"?

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

ii) Mutex มีน้ำหนักเบาและเร็วกว่าเซมาฟอร์ Futex เร็วยิ่งขึ้น

iii) Mutex สามารถรับได้โดยเธรดเดียวกันสำเร็จหลายครั้งโดยมีเงื่อนไขว่าควรปล่อยจำนวนเท่ากัน หัวข้ออื่น ๆ ที่พยายามจะได้รับจะบล็อก ในกรณีของสัญญาณถ้ากระบวนการเดียวกันพยายามที่จะได้รับมันอีกครั้งมันบล็อกเพราะมันสามารถได้มาเพียงครั้งเดียว


ฉันผิด. ii) แหล่งที่มา? iii) มันขึ้นอยู่กับ
curiousguy

6

ความแตกต่างระหว่างเซมาฟอร์แบบไบนารีและ Mutex: OWNERSHIP: เซมาฟอร์สามารถส่งสัญญาณได้ (โพสต์) แม้จากเจ้าของที่ไม่ใช่คนปัจจุบัน หมายความว่าคุณสามารถโพสต์จากกระทู้อื่น ๆ ได้แม้ว่าคุณจะไม่ใช่เจ้าของ

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


5

Mutex ทำงานเพื่อบล็อกพื้นที่สำคัญ แต่เซมาฟอร์ทำงานได้ตามปกติ


5

http://www.geeksforgeeks.org/archives/9102 อธิบายรายละเอียด

Mutexคือกลไกการล็อคที่ใช้ในการซิงโครไนซ์การเข้าถึงทรัพยากร Semaphoreเป็นกลไกการส่งสัญญาณ

มันขึ้นอยู่กับโปรแกรมเมอร์ถ้าเขา / เธอต้องการใช้สัญญาณแบบไบนารีแทน mutex


4

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


ในกรณีพิเศษใดที่รับประกันความยุติธรรมสำหรับเซมาฟอร์ แต่ไม่ใช่สำหรับการปิดเสียง?
curiousguy

1
POSIX มีความต้องการที่เฉพาะเจาะจงซึ่งด้ายควรจะตื่นขึ้นมาด้วยsem_post()สำหรับSCHED_FIFOและSCHED_RR(ทั้งสองคนนี้ยังไม่ได้เริ่มต้น): หัวข้อสำคัญสูงสุดและหากมีหลายที่มีความสำคัญเหมือนกันด้ายที่ได้รับการรอคอยที่ยาวนานที่สุด OpenSolaris ปฏิบัติตามกฎ FIFO นี้ในระดับหนึ่งแม้จะมีการตั้งเวลาปกติ สำหรับ glibc และ FreeBSD การปลดล็อก mutex แบบง่าย ๆ (เช่นไม่ใช่การป้องกันลำดับความสำคัญหรือการสืบทอดลำดับความสำคัญ) และการโพสต์เซมาฟอร์นั้นโดยทั่วไปแล้วการทำเครื่องหมายวัตถุเป็นปลดล็อคแล้ว
jilles

4

ใน windows ความแตกต่างดังต่อไปนี้ MUTEX:กระบวนการที่ดำเนินการรอได้สำเร็จจะต้องดำเนินการสัญญาณและในทางกลับกัน SEMINOR BINARY:กระบวนการที่แตกต่างกันสามารถดำเนินการรอหรือการดำเนินงานสัญญาณในสัญญาณ


4

ในขณะที่ไบนารีสัญญาณอาจใช้เป็น mutex, mutex เป็นกรณีการใช้งานที่เฉพาะเจาะจงมากขึ้นในกระบวนการที่ล็อค mutex เท่านั้นที่ควรจะปลดล็อค ข้อ จำกัด ในการเป็นเจ้าของทำให้สามารถป้องกันได้ดังนี้

  • การเปิดตัวโดยไม่ตั้งใจ
  • การหยุดชะงักแบบเรียกซ้ำ
  • Task Dead Deadlock

ข้อ จำกัด เหล่านี้ไม่ได้มีอยู่เสมอเพราะมันลดความเร็วลง ในระหว่างการพัฒนารหัสของคุณคุณสามารถเปิดใช้งานการตรวจสอบเหล่านี้เป็นการชั่วคราว

เช่นคุณสามารถเปิดใช้งานแอตทริบิวต์การตรวจสอบข้อผิดพลาดใน mutex ของคุณ ข้อผิดพลาดในการตรวจสอบการส่งคืน mutexes EDEADLKหากคุณพยายามล็อกอันเดียวกันสองครั้งและEPERMหากคุณปลดล็อก mutex ที่ไม่ใช่ของคุณ

pthread_mutex_t mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutex_init (&mutex, &attr);

เมื่อเริ่มต้นเราสามารถวางเช็คเหล่านี้ในรหัสของเราเช่นนี้:

if(pthread_mutex_unlock(&mutex)==EPERM)
 printf("Unlock failed:Mutex not owned by this thread\n");

4

แนวคิดชัดเจนสำหรับฉันหลังจากไปโพสต์ด้านบน แต่มีบางคำถามที่ยังอืดอาดอยู่ ดังนั้นฉันจึงเขียนโค้ดขนาดเล็กนี้

เมื่อเราพยายามที่จะให้สัญญาณโดยไม่ได้รับมันจะผ่านไป แต่เมื่อคุณพยายามที่จะให้ mutex โดยไม่รับมันก็ล้มเหลว ฉันทดสอบสิ่งนี้บนแพลตฟอร์ม Windows เปิดใช้งาน USE_MUTEX เพื่อเรียกใช้รหัสเดียวกันโดยใช้ MUTEX

#include <stdio.h>
#include <windows.h>
#define xUSE_MUTEX 1
#define MAX_SEM_COUNT 1

DWORD WINAPI Thread_no_1( LPVOID lpParam );
DWORD WINAPI Thread_no_2( LPVOID lpParam );

HANDLE Handle_Of_Thread_1 = 0;
HANDLE Handle_Of_Thread_2 = 0;
int Data_Of_Thread_1 = 1;
int Data_Of_Thread_2 = 2;
HANDLE ghMutex = NULL;
HANDLE ghSemaphore = NULL;


int main(void)
{

#ifdef USE_MUTEX
    ghMutex = CreateMutex( NULL, FALSE, NULL);
    if (ghMutex  == NULL) 
    {
        printf("CreateMutex error: %d\n", GetLastError());
        return 1;
    }
#else
    // Create a semaphore with initial and max counts of MAX_SEM_COUNT
    ghSemaphore = CreateSemaphore(NULL,MAX_SEM_COUNT,MAX_SEM_COUNT,NULL);
    if (ghSemaphore == NULL) 
    {
        printf("CreateSemaphore error: %d\n", GetLastError());
        return 1;
    }
#endif
    // Create thread 1.
    Handle_Of_Thread_1 = CreateThread( NULL, 0,Thread_no_1, &Data_Of_Thread_1, 0, NULL);  
    if ( Handle_Of_Thread_1 == NULL)
    {
        printf("Create first thread problem \n");
        return 1;
    }

    /* sleep for 5 seconds **/
    Sleep(5 * 1000);

    /*Create thread 2 */
    Handle_Of_Thread_2 = CreateThread( NULL, 0,Thread_no_2, &Data_Of_Thread_2, 0, NULL);  
    if ( Handle_Of_Thread_2 == NULL)
    {
        printf("Create second thread problem \n");
        return 1;
    }

    // Sleep for 20 seconds
    Sleep(20 * 1000);

    printf("Out of the program \n");
    return 0;
}


int my_critical_section_code(HANDLE thread_handle)
{

#ifdef USE_MUTEX
    if(thread_handle == Handle_Of_Thread_1)
    {
        /* get the lock */
        WaitForSingleObject(ghMutex, INFINITE);
        printf("Thread 1 holding the mutex \n");
    }
#else
    /* get the semaphore */
    if(thread_handle == Handle_Of_Thread_1)
    {
        WaitForSingleObject(ghSemaphore, INFINITE);
        printf("Thread 1 holding semaphore \n");
    }
#endif

    if(thread_handle == Handle_Of_Thread_1)
    {
        /* sleep for 10 seconds */
        Sleep(10 * 1000);
#ifdef USE_MUTEX
        printf("Thread 1 about to release mutex \n");
#else
        printf("Thread 1 about to release semaphore \n");
#endif
    }
    else
    {
        /* sleep for 3 secconds */
        Sleep(3 * 1000);
    }

#ifdef USE_MUTEX
    /* release the lock*/
    if(!ReleaseMutex(ghMutex))
    {
        printf("Release Mutex error in thread %d: error # %d\n", (thread_handle == Handle_Of_Thread_1 ? 1:2),GetLastError());
    }
#else
    if (!ReleaseSemaphore(ghSemaphore,1,NULL) )      
    {
        printf("ReleaseSemaphore error in thread %d: error # %d\n",(thread_handle == Handle_Of_Thread_1 ? 1:2), GetLastError());
    }
#endif

    return 0;
}

DWORD WINAPI Thread_no_1( LPVOID lpParam ) 
{ 
    my_critical_section_code(Handle_Of_Thread_1);
    return 0;
}


DWORD WINAPI Thread_no_2( LPVOID lpParam ) 
{
    my_critical_section_code(Handle_Of_Thread_2);
    return 0;
}

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


หากคุณอ่านคำตอบอื่น ๆ เป็นที่ชัดเจนว่าแนวคิดของ "ความเป็นเจ้าของ" นั้นเหมาะสมกับ mutexes เท่านั้นไม่ใช่ semaphores สามารถใช้เซมาฟอร์สำหรับสิ่งต่าง ๆ เช่นเธรดที่ให้เธรดอื่นรู้ว่าการประมวลผลข้อมูลเป็นจำนวนมาก ผลลัพธ์พร้อมที่จะอ่าน
Peter Cordes

2

Mutex ใช้เพื่อป้องกันรหัสที่มีความสำคัญและข้อมูลสัญญาณที่ใช้ในการประสานคุณยังสามารถใช้ในทางปฏิบัติกับการป้องกันรหัสที่ละเอียดอ่อน แต่อาจมีความเสี่ยงที่ปล่อยการป้องกันโดยด้ายอื่น ๆ โดยการดำเนินงาน V.So หลัก ความแตกต่างระหว่าง bi-semaphore และ mutex คือความเป็นเจ้าของยกตัวอย่างเช่นสุขา Mutex ก็เหมือนกับที่เราสามารถเข้าห้องน้ำและล็อคประตูได้ไม่มีใครสามารถเข้าไปได้จนกว่าผู้ชายจะออก ห้องน้ำและล็อคประตู แต่บางคนสามารถเข้ามาได้โดยขอให้ผู้ดูแลระบบเปิดประตูมันไร้สาระ


2

mutex

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

สัญญาณ

สัญญาณเป็นกลไกการส่งสัญญาณ สัญญาณส่งสัญญาณ จำกัด จำนวนผู้ใช้พร้อมกันของทรัพยากรที่ใช้ร่วมกันไม่เกินจำนวนสูงสุด เธรดสามารถร้องขอการเข้าถึงทรัพยากร (การลดเซมาฟอร์) และสามารถส่งสัญญาณว่าพวกเขาเสร็จสิ้นการใช้ทรัพยากร (การเพิ่มเซมาฟอร์) จะช่วยให้จำนวนของด้ายที่ใช้ร่วมกันในการเข้าถึง resources.The การใช้งานที่ถูกต้องของสัญญาณสำหรับการส่งสัญญาณจากงานหนึ่งไป another.semaphores นอกจากนี้ยังสามารถใช้ในการส่งสัญญาณจากงานประจำบริการขัดจังหวะ (ISR) ไปที่งาน การส่งสัญญาณสัญญาณเป็นพฤติกรรม RTOS ที่ไม่ปิดกั้นและทำให้ ISR ปลอดภัย เพราะเทคนิคนี้จะช่วยลดความจำเป็นที่จะต้องเกิดข้อผิดพลาดในการปิดการใช้งานการขัดจังหวะที่ level.This งานที่ทำงานในพื้นที่ว่างของเคอร์เนล


1

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

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

{
    mutexGet();  // Other threads can no longer get the mutex.

    // Make changes to the protected object.
    // ...

    objectModify();  // Also gets/puts the mutex.  Only allowed from this thread context.

    // Make more changes to the protected object.
    // ...

    mutexPut();  // Finally allows other threads to get the mutex.
}

แน่นอนว่าเมื่อใช้งานฟีเจอร์นี้คุณต้องแน่ใจว่าการเข้าถึงทั้งหมดภายในเธรดเดียวนั้นปลอดภัยจริงๆ!

ฉันไม่แน่ใจว่าวิธีการนี้เป็นวิธีการทั่วไปหรือไม่ว่าจะใช้นอกระบบที่ฉันคุ้นเคยหรือไม่ สำหรับตัวอย่างของ mutex ประเภทนี้ให้ดูที่ ThreadX RTOS


2
ประเภทของ mutex ที่คุณกำลังพูดถึงนั้นเรียกว่า "recursive mutex" และควรหลีกเลี่ยงเนื่องจากมันช้าและมักจะส่งเสริมการออกแบบที่ไม่ดี: (ดู David Butenhof: zaval.org/resources/library/butenhof1.html )
gaspard

ตกลง ในระบบปฏิบัติการนี้โดยเฉพาะฉันใช้บริการ mutex ที่ฉันต้องการให้ชัดเจนว่ารหัสนั้นสำหรับ "การยกเว้นซึ่งกันและกัน" และไม่ใช่การนับการอ้างอิง แต่ฉันไม่ได้ใช้คุณลักษณะแบบเรียกใช้ซ้ำเพราะกลัวว่าจะคลายความน่าเกลียด อย่างไรก็ตามในบริบทของคำถามนี่เป็นข้อแตกต่างที่สำคัญระหว่าง "mutex" และ "สัญญาณแบบไบนารี"
Casey Barker

1

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


ความเป็นเจ้าของคืออะไรคุณหมายถึงบริบทที่ได้รับ mutex เท่านั้นที่สามารถยกเลิกได้
Raulp

1

ในฐานะที่เป็นคนมากมายที่นี่ได้กล่าวถึงการ mutex ถูกนำมาใช้เพื่อปกป้องชิ้นส่วนที่สำคัญของรหัส (ส่วนที่สำคัญ AKA.) คุณจะได้รับ mutex (ล็อค) ใส่ส่วนที่สำคัญและปล่อย mutex (ปลดล็อค) ทั้งหมดในหัวข้อเดียวกัน

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


1

ทางออกที่ดีที่สุด

ข้อแตกต่างเพียงอย่างเดียวคือ

1.Mutex -> การล็อกและปลดล็อกอยู่ภายใต้กรรมสิทธิ์ของเธรดที่ล็อค mutex

2.Semaphore -> ไม่มีความเป็นเจ้าของเช่น; หากหนึ่งเธรดเรียก semwait (s) เธรดอื่นใดสามารถเรียก sempost (s) เพื่อลบการล็อก


1

mutex

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

ความเรียบง่ายและประสิทธิภาพของ mutex นั้นมาจากข้อ จำกัด เพิ่มเติมที่กำหนดให้กับผู้ใช้ของตนมากกว่าและมากกว่าสิ่งที่สัญญาณต้องการ ซึ่งแตกต่างจากสัญญาณที่ใช้พื้นฐานที่สุดของพฤติกรรมตามการออกแบบดั้งเดิมของ Dijkstra, mutex มีกรณีการใช้งานที่เข้มงวดและแคบ: n งานเดียวสามารถถือ mutex ในเวลาเดียว นั่นคือการใช้งานการนับบน mutex นั้นจะเป็นหนึ่งเสมอ

  1. ใครก็ตามที่ล็อค mutex จะต้องปลดล็อค นั่นคือคุณไม่สามารถล็อก mutex ในบริบทหนึ่งและปลดล็อกในอีกบริบทหนึ่ง ซึ่งหมายความว่า mutex ไม่เหมาะสำหรับการซิงโครไนซ์ที่ซับซ้อนระหว่างเคอร์เนลและพื้นที่ผู้ใช้ กรณีการใช้งานส่วนใหญ่จะล็อคและปลดล็อกอย่างหมดจดจากบริบทเดียวกัน
  2. ไม่อนุญาตการล็อกซ้ำและการปลดล็อค นั่นคือคุณไม่สามารถรับ mutex เดียวกันซ้ำและคุณไม่สามารถปลดล็อก mutex ที่ถูกปลดล็อกได้
  3. กระบวนการไม่สามารถออกได้ในขณะที่ถือ mutex
  4. ไม่สามารถรับ mutex ได้โดยตัวจัดการขัดจังหวะหรือครึ่งล่างแม้กระทั่งกับ mutex_trylock ()
  5. mutex สามารถจัดการได้ผ่านทาง API อย่างเป็นทางการเท่านั้น: จะต้องเริ่มต้นผ่านวิธีการที่อธิบายไว้ในส่วนนี้และไม่สามารถคัดลอก, เริ่มต้นด้วยมือหรือเริ่มต้นใหม่ได้

[1] การพัฒนาเคอร์เนล Linux รุ่นที่สาม Robert Love


1

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

ความแตกต่างที่สำคัญระหว่างไบนารีสัญญาณและ mutex คือสัญญาณสัญญาณเป็นกลไกการส่งสัญญาณและ mutex เป็นกลไกการล็อค แต่สัญญาณสัญญาณไบนารีดูเหมือนว่าจะทำงานเหมือน mutex ที่สร้างความสับสน แต่ทั้งสองแนวคิดที่แตกต่างกันเหมาะสำหรับงานที่แตกต่างกัน

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