สองเซ็นต์ของฉันใน SpinLock ใน. Net

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

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

SpinLock คืออะไรและทำไมถึงต้องการ?

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

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

โดยทั่วไปแล้ว SpinLock จะใช้เมื่อทำงานกับอินเทอร์รัปต์เพื่อดำเนินการรอไม่ว่างภายในลูปจนกว่าทรัพยากรจะพร้อมใช้งาน SpinLock ไม่ทำให้เธรดถูกจองไว้ล่วงหน้า แต่จะยังคงหมุนต่อไปจนกว่าการล็อกทรัพยากรจะถูกปล่อยออกมา

การเขียนโปรแกรม SpinLock ใน. Net

โปรดสังเกตว่า SpinLock ถูกกำหนดให้เป็นโครงสร้างใน. Net กล่าวคือถูกกำหนดเป็นประเภทค่าด้วยเหตุผลด้านประสิทธิภาพ ดังนั้นหากคุณกำลังส่งผ่านอินสแตนซ์ SpinLock คุณควรส่งต่อโดยอ้างอิงไม่ใช่ตามมูลค่า ในส่วนนี้เราจะมาดูว่าเราสามารถตั้งโปรแกรม SpinLock ใน. Net ได้อย่างไร ในการใช้ SpinLock ใน. Net คุณจะต้องใช้ประโยชน์จากคลาส SpinLock ที่มีอยู่ใน System.Threading namespace

รายการรหัสต่อไปนี้แสดงวิธีใช้ SpinLock ใน. Net

SpinLock spinLock = new SpinLock (true);

bool isLocked = false;

try

{

spinLock.Enter (ref isLocked);

// Write your usual code here

}

finally

{

if (isLocked)

   spinLock.Exit();

}

SpinWait

โปรดทราบว่าเช่นเดียวกับ SpinLock SpinWait ยังเป็นโครงสร้างและไม่ใช่คลาส เช่นเดียวกับ SpinLock คุณสามารถใช้ SpinWait เพื่อเขียนรหัสการซิงโครไนซ์แบบล็อกฟรีที่สามารถ "หมุน" แทนที่จะบล็อก SpinWait สามารถใช้เพื่อลดการใช้ทรัพยากรโดยทำการกรอ CPU อย่างเข้มข้นเป็นเวลา 10 โพสต์ซ้ำซึ่งจะให้การควบคุมโดยการเรียก Thread.Yield และ Thread.Sleep กล่าวอีกนัยหนึ่ง SpinWait สามารถใช้เพื่อ จำกัด การหมุนที่ใช้ CPU เป็นจำนวนที่แน่นอน MSDN ระบุว่า: "System.Threading.SpinWait เป็นประเภทการซิงโครไนซ์ที่มีน้ำหนักเบาซึ่งคุณสามารถใช้ในสถานการณ์ระดับต่ำเพื่อหลีกเลี่ยงการสลับบริบทที่มีราคาแพงและการเปลี่ยนเคอร์เนลที่จำเป็นสำหรับเหตุการณ์เคอร์เนล"

ในการใช้ SpinWait ในโค้ดของคุณคุณสามารถใช้ประโยชน์จากเมธอด SpinUntil () แบบคงที่ของโครงสร้าง SpinWait หรือใช้ประโยชน์จากวิธี SpinOnce () แบบไม่คงที่ ข้อมูลโค้ดต่อไปนี้แสดงให้เห็นว่าสามารถใช้ SpinWait ได้อย่างไร

SpinWait spinWait = new SpinWait();

bool shouldSpin;

while (!shouldSpin)

{

   Thread.MemoryBarrier(); spinWait.SpinOnce();

}