แนวทางปฏิบัติที่ดีที่สุดสำหรับการซิงโครไนซ์เธรด. Net

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

บทความนี้นำเสนอการอภิปรายเกี่ยวกับแนวคิดที่เกี่ยวข้องกับการซิงโครไนซ์และความปลอดภัยของเธรดใน. Net และแนวทางปฏิบัติที่ดีที่สุดที่เกี่ยวข้อง

ล็อคพิเศษ

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

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

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

ข้อมูลโค้ดต่อไปนี้แสดงให้เห็นว่าคุณสามารถใช้การซิงโครไนซ์โดยใช้คลาส Monitor ได้อย่างไร

private static readonly object lockObj = new object();

        static void Main(string[] args)

        {

            Monitor.Enter(lockObj);

                       try

            {

               //Some code

            }

                  finally

            {

                Monitor.Exit(lockObj);

            }

        }

รหัสที่เทียบเท่าโดยใช้คีย์เวิร์ดล็อคจะมีลักษณะคล้ายกับสิ่งนี้:

    private static readonly object lockObj = new object();

        static void Main(string[] args)

        {  

            try

            {

                lock(lockObj)

                {

                    //Some code

                }             

            }

            finally

            {

                //You can release any resources here

            }

        }

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

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

ล็อคแบบไม่ผูกขาด

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

  • Semaphore - ใช้เพื่อ จำกัด จำนวนเธรดที่สามารถเข้าถึงทรัพยากรที่แชร์พร้อมกันได้ โดยพื้นฐานแล้วจะใช้เพื่อ จำกัด จำนวนผู้บริโภคสำหรับทรัพยากรที่ใช้ร่วมกันโดยเฉพาะพร้อมกัน
  • SemaphoreSlim - ทางเลือกที่รวดเร็วและน้ำหนักเบาสำหรับคลาส Semaphore เพื่อใช้การล็อกแบบไม่ผูกขาด
  • ReaderWriterLockSlim - คลาส ReaderWriterLockSlim ถูกนำมาใช้ใน. Net Framework 3.5 แทนคลาส ReaderWriterLock

คุณสามารถใช้คลาส ReaderWriterLockSlim เพื่อรับการล็อกแบบไม่ผูกขาดบนทรัพยากรที่ใช้ร่วมกันซึ่งจะต้องมีการอ่านบ่อย แต่ไม่บ่อย ดังนั้นแทนที่จะใช้การล็อกแบบพิเศษร่วมกันบนทรัพยากรที่ใช้ร่วมกันซึ่งต้องการการอ่านบ่อยๆและการอัปเดตไม่บ่อยนักคุณสามารถใช้คลาสนี้เพื่อรับการล็อกการอ่านบนทรัพยากรที่แชร์และการล็อกการเขียนเฉพาะ

การหยุดชะงัก

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