"สวัสดี Amigo! คุณจำได้ว่า Ellie บอกคุณเกี่ยวกับปัญหาที่เกิดขึ้นเมื่อหลายเธรดพยายามเข้าถึงทรัพยากรที่ใช้ร่วมกันพร้อมกันใช่ไหม"
"ใช่."
“นั่นไม่ใช่ทั้งหมด มีปัญหาเล็กๆ อีกปัญหาหนึ่ง”
อย่างที่คุณทราบ คอมพิวเตอร์มีหน่วยความจำที่เก็บข้อมูลและคำสั่ง (รหัส) เช่นเดียวกับตัวประมวลผลที่ดำเนินการคำสั่งเหล่านี้และทำงานกับข้อมูล โปรเซสเซอร์อ่านข้อมูลจากหน่วยความจำ เปลี่ยนแปลง และเขียนข้อมูลกลับไปยังหน่วยความจำ เพื่อเพิ่มความเร็วในการคำนวณ โปรเซสเซอร์มีหน่วยความจำ "เร็ว" ในตัว: แคช
โปรเซสเซอร์ทำงานเร็วขึ้นโดยการคัดลอกตัวแปรและพื้นที่หน่วยความจำที่ใช้บ่อยที่สุดไปยังแคช จากนั้นจะทำการเปลี่ยนแปลงทั้งหมดในหน่วยความจำที่รวดเร็วนี้ จากนั้นจะคัดลอกข้อมูลกลับไปยังหน่วยความจำ «ช้า» ทั้งหมดนี้ หน่วยความจำที่ช้ามีตัวแปรเก่า (ไม่เปลี่ยนแปลง!)
นี่คือจุดที่ปัญหาเกิดขึ้น เธรดหนึ่งเปลี่ยนตัวแปรเช่น isCancel หรือ isInterrupted ในตัวอย่างข้างต้น แต่เธรดที่สอง «ไม่เห็นการเปลี่ยนแปลงนี้เนื่องจากเกิดขึ้นในหน่วยความจำแบบเร็ว นี่เป็นผลมาจากข้อเท็จจริงที่ว่าเธรดไม่มีสิทธิ์เข้าถึงแคชของกันและกัน (โปรเซสเซอร์มักประกอบด้วยคอร์อิสระหลายคอร์ และเธรดสามารถทำงานบนคอร์ที่แตกต่างกันได้)
จำตัวอย่างเมื่อวาน:
รหัส | คำอธิบาย |
---|---|
|
เธรด «ไม่รู้» ว่ามีเธรดอื่นอยู่
ในวิธีการเรียกใช้ ตัวแปร isCancel จะถูกใส่ลงในแคชของเธรดลูกเมื่อถูกใช้เป็นครั้งแรก การดำเนินการนี้เทียบเท่ากับรหัสต่อไปนี้:
การเรียก วิธี การยกเลิกจากเธรดอื่นจะเปลี่ยนค่าของisCancelในหน่วยความจำปกติ (ช้า) แต่ไม่อยู่ในแคชของเธรดอื่น |
|
"ว้าว! และพวกเขาคิดวิธีแก้ปัญหาที่สวยงามสำหรับสิ่งนี้ด้วย เช่นซิง โครไนซ์ ?"
"คุณจะไม่เชื่อ!"
ความคิดแรกคือการปิดใช้งานแคช แต่สิ่งนี้ทำให้โปรแกรมทำงานช้าลงหลายเท่า จากนั้นทางออกอื่นก็เกิดขึ้น
เกิดคำหลักที่ผันผวน เราใส่คีย์เวิร์ดนี้ไว้หน้าการประกาศตัวแปรเพื่อระบุว่าค่าของคีย์เวิร์ดไม่ต้องใส่ในแคช แม่นยำกว่านั้น ไม่ใช่ว่าไม่สามารถใส่ลงในแคชได้ แต่เป็นเพียงว่าต้องอ่านและเขียนจากหน่วยความจำปกติ (ช้า) เสมอ
ต่อไปนี้เป็นวิธีแก้ไขปัญหาของเราเพื่อให้ทุกอย่างทำงานได้ดี:
รหัส | คำอธิบาย |
---|---|
|
โมดิฟายเออร์ระเหยทำให้ตัวแปรถูกอ่านและเขียนไปยังหน่วยความจำปกติที่ใช้ร่วมกันโดยเธรดทั้งหมดเสมอ |
|
"แค่นั้นแหละ?"
"นั่นแหล่ะ เรียบง่ายและสวยงาม"
GO TO FULL VERSION