Java Semaphore และ Mutex คืออะไร – Java Concurrency MultiThread อธิบายด้วย Example

เผยแพร่แล้ว: 2015-03-12

Java Mutex และ Semaphore Tutorial โดย Crunchify

Java Concurrency เป็นหัวข้อที่กว้างมาก มีบทช่วยสอนและตัวอย่างหลายร้อยรายการให้ใช้งาน เมื่อก่อนฉันได้เขียนบทช่วยสอนเกี่ยวกับ Run Multiple Threads พร้อมกันใน Java และ Synchronized Blocks ประเภทต่างๆ

ในบทช่วยสอนนี้เราจะพูดถึง:

  1. คำอธิบายของ Mutex
  2. คำอธิบายของ Semaphore
  3. สองตัวอย่างพร้อมรายละเอียด

มาเริ่มกันเลย

Let's keep this in mind ขณะที่อ่านคำอธิบายด้านล่าง:

  • ยกตัวอย่างนักช้อปและลูกค้า
  • นักช้อปกำลังยืมแล็ปท็อป
  • ลูกค้าสามารถมาและใช้แล็ปท็อปได้ – ลูกค้าต้องการรหัสเพื่อใช้แล็ปท็อป
  • หลังการใช้งาน – ลูกค้าสามารถคืนโน้ตบุ๊กให้นักช้อปได้

Mutex คืออะไร (เพียง 1 เธรด):

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

Official Definition :

“โดยทั่วไป Mutex จะใช้เพื่อทำให้เป็นอนุกรมในการเข้าถึงส่วนของ re-entrant code ที่ cannot be executed concurrently ได้มากกว่าหนึ่งเธรด ออบเจ็กต์ mutex อนุญาตเพียงหนึ่งเธรดในส่วนที่ถูกควบคุม บังคับให้เธรดอื่นที่พยายามเข้าถึงส่วนนั้นเพื่อรอจนกว่าเธรดแรกจะออกจากส่วนนั้น”

กล่าวอีกนัยหนึ่ง: Mutex = Mutually Exclusive Semaphore

Semaphore คืออะไร (N เธรดที่ระบุ):

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

Official Definition : “สัญญาณจะจำกัดจำนวนผู้ใช้ทรัพยากรที่ใช้ร่วมกันพร้อมกันสูงสุดจำนวนสูงสุด เธรดสามารถร้องขอการเข้าถึงทรัพยากร (ลดสัญญาณ) และสามารถส่งสัญญาณว่าพวกเขาใช้ทรัพยากรเสร็จแล้ว (เพิ่มสัญญาณ)”

ต้องอ่านอีกเรื่อง: Lazy Creation of Singleton ThreadSafe Instance

ตัวอย่างที่ 1: (คำอธิบายด้านล่าง)

ในบทช่วยสอนด้านบน CrunchifySemaphoreMutexTutorial.java เมื่อ CrunchifyProducer เพิ่ม threadName ให้กับวัตถุ crunchifyList linkedList มันสามารถส่งสัญญาณสัญญาณ

จากนั้น CrunchifyConsumer สามารถพยายามรับสัญญาณ ดังนั้นพวกเขาจะรอจนกว่า CrunchifyProducer จะส่งสัญญาณว่ามีการเพิ่ม threadID เมื่อส่งสัญญาณข้อมูลเพิ่มเติม ผู้บริโภครายหนึ่งจะถูกปลุกและจะรู้ว่าสามารถอ่านวัตถุ crunchifyList ได้ สามารถอ่านรายการแล้วกลับไปพยายามหาสัญญาณ

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

กล่าวอีกนัยหนึ่ง:

ผลลัพธ์:

วิธีป้องกันสภาพการแข่งขัน:

What if you have multiple Consumers? ในบทช่วยสอน Java ด้านบน ผู้บริโภค (ไม่ใช่ผู้ผลิต) ควรล็อกบัฟเฟอร์เมื่ออ่านแพ็กเก็ต (แต่ไม่ใช่เมื่อได้รับสัญญาณ) เพื่อป้องกันสภาวะการแข่งขัน ในตัวอย่างด้านล่าง โปรดิวเซอร์ล็อกรายการด้วยเนื่องจากทุกอย่างอยู่ใน JVM เดียวกัน

ตัวอย่าง-2:

ผลลัพธ์: