ทำไมการใช้งาน mutex ส่วนใหญ่จึงไม่ยุติธรรม?


11

ความเข้าใจของฉันคือการใช้งาน mutex ที่นิยมมากที่สุด (เช่น std :: mutex ใน C ++) ไม่รับประกันความเป็นธรรม - นั่นคือพวกเขาไม่รับประกันว่าในกรณีของการช่วงชิงการล็อคจะถูกรับโดยเธรดตามลำดับที่พวกเขา เรียกว่าล็อค () ในความเป็นจริงมันเป็นไปได้ (แม้จะหวังว่าผิดปกติ) ว่าในกรณีที่มีการโต้แย้งสูงบางกระทู้ที่รอรับ mutex อาจไม่เคยได้รับ

นี่ดูเหมือนว่าพฤติกรรมที่ไม่ช่วยเหลือฉัน - ดูเหมือนว่า mutex ที่ยุติธรรมจะให้ผลการทำงานที่สอดคล้องกับสิ่งที่โปรแกรมเมอร์ต้องการ / คาดหวัง

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

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


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

ฉันคิดว่าใช้กลไกลิสต์ลิงก์ที่ไม่มีลิสต์ โครงสร้างข้อมูลใดไม่ใช้ mutex ที่ไม่เป็นธรรมเพื่อค้นหาเธรดถัดไปที่จะปลุก
Jeremy Friesner

1
คุณจะต้องมองหาสิ่งนั้น แต่รายการลิงก์ที่ไม่มีล็อครับประกันความเป็นธรรมหรือไม่? ฉันคิดว่าคุณจะพบว่าการรับประกันเช่นความยุติธรรมในการเขียนโปรแกรมพร้อมกันยากที่จะเกิดขึ้น
user3543290

คำตอบ:


7

คำตอบของ Jim Sawyer ชี้ไปที่คำตอบเดียว: เมื่อคุณมีเธรดที่มีลำดับความสำคัญต่างกันพฤติกรรม "ยุติธรรม" จะไม่ถูกต้อง เมื่อคุณมีหลายเธรดที่สามารถรันได้เธรดที่มีลำดับความสำคัญสูงสุดมักเป็นเธรดที่ควรรัน

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

ตัวอย่างทั่วไปคือตัวจัดการสัญญาณใน Unix ตัวดักระบบแบบอะซิงโครนัสใน VMS หรือการเรียกขั้นตอนแบบอะซิงโครนัสใน Windows NT สิ่งเหล่านี้ล้วนเป็นสิ่งเดียวกัน: ระบบปฏิบัติการจำเป็นต้องแจ้งให้ทราบถึงกระบวนการของผู้ใช้ว่ามีเหตุการณ์บางอย่างเกิดขึ้นและสิ่งนี้จะถูกจัดการโดยการรันโค้ดในพื้นที่ผู้ใช้

บริการระบบปฏิบัติการจำนวนมากเช่น I / O แบบอะซิงโครนัสมักจะนำมาใช้ด้านบนของสถานที่นี้

อีกตัวอย่างคือถ้ากระบวนการอยู่ภายใต้การควบคุมของดีบักเกอร์ ในกรณีดังกล่าวระบบการดีบักอาจเรียกใช้รหัสเป็นงานผู้ใช้ด้วยเหตุผลต่างๆ


4

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


ยินดีต้อนรับสู่เว็บไซต์และขอขอบคุณสำหรับการตอบคำถามที่มีมานานแล้วโดยไม่มีคำตอบ! แน่นอนคำตอบของคุณถูกต้องแล้ว แต่ฉันรู้สึกว่ามันอาจมีรายละเอียดเพิ่มเติมเล็กน้อย
David Richerby

3

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

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

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