ล็อค (วิทยาการคอมพิวเตอร์)

จากวิกิพีเดีย สารานุกรมเสรี
ข้ามไปที่การนำทาง ข้ามไปที่การค้นหา

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

ประเภท

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

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

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

ล็อคโดยทั่วไปต้องการการสนับสนุนฮาร์ดแวร์สำหรับการใช้งานอย่างมีประสิทธิภาพ การสนับสนุนนี้มักจะอยู่ในรูปของ คำสั่ง อะตอม มิกตั้งแต่หนึ่ง คำสั่งขึ้นไป เช่น " test-and-set ", " fetch-and-add " หรือ " comparison-and-swap " คำแนะนำเหล่านี้อนุญาตให้กระบวนการเดียวทดสอบว่าล็อคว่างหรือไม่ และหากว่าง ให้รับล็อคในการดำเนินการแบบอะตอมเดียว

สถาปัตยกรรมUniprocessor มีตัวเลือกในการใช้ ลำดับคำสั่งต่อเนื่อง—โดยใช้คำสั่งพิเศษหรือคำนำหน้าคำสั่งเพื่อปิดใช้งานการขัดจังหวะชั่วคราว—แต่เทคนิคนี้ใช้ไม่ได้กับเครื่องหน่วยความจำที่ใช้ร่วมกันแบบมัลติโปรเซสเซอร์ การสนับสนุนที่เหมาะสมสำหรับการล็อกในสภาพแวดล้อมแบบมัลติโปรเซสเซอร์อาจต้องการการสนับสนุนฮาร์ดแวร์หรือซอฟต์แวร์ที่ค่อนข้างซับซ้อน โดยมีปัญหา การ ซิงโครไนซ์ จำนวนมาก

เหตุผลที่ จำเป็นต้องมี การดำเนินการปรมาณูเป็นเพราะการทำงานพร้อมกันซึ่งมีงานมากกว่าหนึ่งงานดำเนินการตรรกะเดียวกัน ตัวอย่างเช่น พิจารณารหัส C ต่อไปนี้:

ถ้า( ล็อค== 0 ) {    
    // ล็อคฟรี ตั้งค่า
ล็อค= myPID ;      
}

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

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

บางภาษารองรับการล็อกแบบวากยสัมพันธ์ ตัวอย่างในC #มีดังนี้:

 บัญชีคลาส สาธารณะ// นี่คือการตรวจสอบบัญชี{ ทศนิยมส่วนตัว_balance = 0 ; วัตถุส่วนตัว_balanceLock = วัตถุใหม่(); 

        
         

     เงินฝากเป็นโมฆะ สาธารณะ( จำนวนทศนิยม) { // ครั้งละหนึ่งเธรดเท่านั้นที่สามารถดำเนินการคำสั่งนี้ได้ ล็อค( _balanceLock ) { _balance += จำนวน; } } 
    
        
         
        
              
        
    

     โมฆะ สาธารณะถอน( จำนวนทศนิยม ) { // ครั้งละหนึ่งเธรดเท่านั้นที่สามารถดำเนินการคำสั่งนี้ได้ ล็อค( _balanceLock ) { _balance -= จำนวน; } } }
    
        
         
        
              
        
    

รหัสlock(this)อาจนำไปสู่ปัญหาหากอินสแตนซ์สามารถเข้าถึงได้แบบสาธารณะ [1]

เช่นเดียวกับJava C# ยังสามารถซิงโครไนซ์วิธีการทั้งหมดโดยใช้แอตทริบิวต์ MethodImplOptions.Synchronized [2] [3]

[MethodImpl (MethodImplOptions.Synchronized)] 
โมฆะสาธารณะ SomeMethod () { // ทำสิ่ง ต่าง ๆ } 

    

ความละเอียด

ก่อนที่จะได้รับการแนะนำให้รู้จักกับรายละเอียดการล็อก เราต้องเข้าใจแนวคิดสามประการเกี่ยวกับการล็อก:

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

มีข้อแลกเปลี่ยนระหว่างการลดโอเวอร์เฮดของการล็อกและการลดช่วงชิงการล็อกเมื่อเลือกจำนวนการล็อกในการซิงโครไนซ์

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

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

ล็อคฐานข้อมูล

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

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

  • การ ล็อกในแง่ร้าย : ผู้ใช้ที่อ่านบันทึกโดยมีเจตนาที่จะอัปเดตจะล็อกเอกสิทธิ์ในระเบียนเพื่อป้องกันไม่ให้ผู้ใช้รายอื่นจัดการ ซึ่งหมายความว่าไม่มีใครสามารถจัดการบันทึกนั้นได้จนกว่าผู้ใช้จะปลดล็อค ข้อเสียคือผู้ใช้สามารถถูกล็อคไว้ได้เป็นเวลานาน ซึ่งจะทำให้การตอบสนองของระบบโดยรวมช้าลงและทำให้เกิดความคับข้องใจ
จะใช้การล็อกในแง่ร้ายได้ที่ไหน: ใช้เป็นหลักในสภาพแวดล้อมที่การโต้แย้งข้อมูล (ระดับของผู้ใช้ที่ร้องขอต่อระบบฐานข้อมูลในแต่ละครั้ง) เป็นเรื่องที่หนักมาก โดยที่ค่าใช้จ่ายในการปกป้องข้อมูลผ่านการล็อคจะน้อยกว่าค่าใช้จ่ายในการย้อนกลับธุรกรรม หากเกิดความขัดแย้งขึ้นพร้อมกัน การทำงานพร้อมกันแบบมองโลกในแง่ร้ายจะดีที่สุดเมื่อเวลาล็อคสั้นลง เช่นเดียวกับในการประมวลผลบันทึกแบบเป็นโปรแกรม การทำงานพร้อมกันที่มองโลกในแง่ร้ายต้องการการเชื่อมต่อแบบถาวรกับฐานข้อมูล และไม่ใช่ตัวเลือกที่ปรับขนาดได้เมื่อผู้ใช้โต้ตอบกับข้อมูล เนื่องจากเรกคอร์ดอาจถูกล็อกเป็นระยะเวลาที่ค่อนข้างใหญ่ ไม่เหมาะสำหรับใช้ในการพัฒนาเว็บแอปพลิเคชัน
  • ล็อคในแง่ดี: อนุญาตให้ผู้ใช้หลายรายเข้าถึงฐานข้อมูลพร้อมกันในขณะที่ระบบเก็บสำเนาของการอ่านเริ่มต้นโดยผู้ใช้แต่ละราย เมื่อผู้ใช้ต้องการอัปเดตเรกคอร์ด แอปพลิเคชันจะกำหนดว่าผู้ใช้รายอื่นเปลี่ยนเรกคอร์ดตั้งแต่อ่านครั้งล่าสุดหรือไม่ แอปพลิเคชันทำสิ่งนี้โดยเปรียบเทียบการอ่านครั้งแรกที่เก็บไว้ในหน่วยความจำกับบันทึกฐานข้อมูลเพื่อตรวจสอบการเปลี่ยนแปลงที่ทำกับบันทึก ความคลาดเคลื่อนใดๆ ระหว่างการอ่านครั้งแรกและบันทึกฐานข้อมูลละเมิดกฎการทำงานพร้อมกัน และทำให้ระบบเพิกเฉยต่อคำขออัปเดตใดๆ มีการสร้างข้อความแสดงข้อผิดพลาดและขอให้ผู้ใช้เริ่มกระบวนการอัปเดตอีกครั้ง ปรับปรุงประสิทธิภาพของฐานข้อมูลโดยการลดจำนวนการล็อกที่จำเป็น ซึ่งจะช่วยลดภาระงานบนเซิร์ฟเวอร์ฐานข้อมูล มันทำงานอย่างมีประสิทธิภาพกับตารางที่ต้องการการอัปเดตที่จำกัด เนื่องจากไม่มีผู้ใช้ที่ถูกล็อค อย่างไรก็ตาม การอัปเดตบางอย่างอาจล้มเหลว ข้อเสียคือความล้มเหลวในการอัปเดตอย่างต่อเนื่องเนื่องจากมีคำขออัปเดตจำนวนมากจากผู้ใช้พร้อมกันหลายราย ซึ่งอาจทำให้ผู้ใช้รู้สึกหงุดหงิด
จะใช้การล็อกในแง่ดีได้ที่ไหน: เหมาะสมในสภาพแวดล้อมที่มีความขัดแย้งสำหรับข้อมูลต่ำ หรือเมื่อจำเป็นต้องเข้าถึงข้อมูลแบบอ่านอย่างเดียว การทำงานพร้อมกันในแง่ดีนั้นถูกใช้อย่างกว้างขวางใน .NET เพื่อตอบสนองความต้องการของแอปพลิเคชั่นมือถือและที่ไม่ได้เชื่อมต่อ[4]ซึ่งการล็อคแถวข้อมูลเป็นเวลานานจะเป็นไปไม่ได้ นอกจากนี้ การรักษาล็อกเร็กคอร์ดจำเป็นต้องมีการเชื่อมต่อแบบถาวรกับเซิร์ฟเวอร์ฐานข้อมูล ซึ่งไม่สามารถทำได้ในแอปพลิเคชันที่ตัดการเชื่อมต่อ

ข้อเสีย

การป้องกันทรัพยากรแบบล็อกและการซิงโครไนซ์เธรด/กระบวนการมีข้อเสียหลายประการ:

  • ความขัดแย้ง: เธรด/กระบวนการบางอย่างต้องรอจนกว่าล็อก (หรือล็อกทั้งชุด) จะออก หากเธรดตัวใดตัวหนึ่งที่มีตัวล็อคตาย ตัวหยุด บล็อก หรือเข้าสู่วงรอบที่ไม่มีที่สิ้นสุด เธรดอื่นๆ ที่รอการล็อคอาจรอตลอดไป
  • ค่าโสหุ้ย: การใช้ล็อคจะเพิ่มค่าใช้จ่ายสำหรับการเข้าถึงทรัพยากรแต่ละครั้ง แม้ว่าโอกาสในการชนกันจะน้อยมาก (อย่างไรก็ตาม โอกาสที่จะเกิดการชนกันนั้นเป็นสภาวะการแข่งขัน )
  • การดีบัก: บั๊กที่เกี่ยวข้องกับการล็อกขึ้นอยู่กับเวลาและอาจมีความละเอียดอ่อนมากและยากที่จะทำซ้ำได้ เช่น การชะงักงัน
  • ความไม่เสถียร: ความสมดุลที่เหมาะสมระหว่างค่าโสหุ้ยในการล็อกและความขัดแย้งในการล็อกสามารถเกิดขึ้นได้เฉพาะกับโดเมนของปัญหา (แอปพลิเคชัน) และมีความละเอียดอ่อนต่อการออกแบบ การนำไปใช้งาน และการเปลี่ยนแปลงทางสถาปัตยกรรมระบบระดับต่ำ เครื่องชั่งเหล่านี้อาจเปลี่ยนแปลงไปตามวงจรชีวิตของแอปพลิเคชัน และอาจนำมาซึ่งการเปลี่ยนแปลงครั้งใหญ่ในการอัปเดต (ปรับสมดุลใหม่)
  • ความสามารถในการเขียนได้: การล็อกสามารถประกอบได้เท่านั้น (เช่น การจัดการการล็อกหลายชุดพร้อมกันเพื่อลบรายการ X ออกจากตาราง A และแทรก X ลงในตาราง B) โดยใช้ซอฟต์แวร์สนับสนุนที่ค่อนข้างซับซ้อน (โอเวอร์เฮด) และการยึดเกาะที่สมบูรณ์แบบโดยการเขียนโปรแกรมแอปพลิเคชันตามระเบียบข้อบังคับที่เข้มงวด
  • การผกผันของลำดับความสำคัญ : เธรด/กระบวนการที่มีลำดับความสำคัญต่ำซึ่งมีการล็อกทั่วไปสามารถป้องกันไม่ให้เธรด/กระบวนการที่มีลำดับความสำคัญสูงดำเนินการต่อไปได้ การ สืบทอดลำดับความสำคัญสามารถใช้เพื่อลดระยะเวลาการผกผันของลำดับความสำคัญได้ สามารถใช้ โปรโตคอลเพดานลำดับความสำคัญได้บนระบบตัวประมวลผลเดียวเพื่อลดระยะเวลาการผกผันลำดับความสำคัญในกรณีที่แย่ที่สุด รวมทั้งป้องกันการชะงักงัน
  • Convoying : เธรดอื่น ๆ ทั้งหมดต้องรอหากเธรดที่ล็อคตัวล็อคถูกเลื่อนออกไปเนื่องจากการขัดจังหวะการแบ่งเวลาหรือหน้ามีข้อบกพร่อง

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

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

ขาดการเรียบเรียง

ปัญหาที่ใหญ่ที่สุดอย่างหนึ่งของการเขียนโปรแกรมแบบใช้ล็อกคือ "การล็อกไม่ประกอบด้วย ": เป็นการยากที่จะรวมโมดูลที่ใช้ล็อกขนาดเล็กและถูกต้องเข้าไว้ในโปรแกรมขนาดใหญ่ที่มีความถูกต้องเท่าเทียมกันโดยไม่ต้องแก้ไขโมดูลหรืออย่างน้อยก็รู้เกี่ยวกับภายใน Simon Peyton Jones (ผู้สนับสนุนซอฟต์แวร์หน่วยความจำธุรกรรม ) ให้ตัวอย่างต่อไปนี้ของแอปพลิเคชันธนาคาร: [5] ออกแบบ บัญชี คลาสที่อนุญาตให้ลูกค้าหลายรายฝากหรือถอนเงินเข้าบัญชี และให้อัลกอริธึมในการโอนเงินจากบัญชีหนึ่งไปยังอีกบัญชีหนึ่ง วิธีแก้ปัญหาแบบล็อกสำหรับส่วนแรกของปัญหาคือ:

บัญชี
     คลาส : ยอด สมาชิก : สมาชิกจำนวนเต็ม
     mutex: Lock

    วิธีการฝาก (n: จำนวนเต็ม)
           mutex.lock()
           สมดุล ← สมดุล + n
           mutex.unlock()

    วิธีการถอน (n: จำนวนเต็ม)
           เงินฝาก(-n)

ส่วนที่สองของปัญหานั้นซับซ้อนกว่ามาก รูทีน การถ่ายโอนที่ถูกต้องสำหรับโปรแกรมต่อเนื่องจะเป็น

การโอน ฟังก์ชัน (จาก: บัญชี ถึง: บัญชี จำนวน: จำนวนเต็ม)
    จาก.ถอน (จำนวนเงิน)
    ที่ฝาก (จำนวนเงิน)

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

ฟังก์ชั่นการถ่ายโอน (จาก: บัญชี, ถึง: บัญชี, จำนวน: จำนวนเต็ม)
     ถ้าจาก < ถึง     // สั่งการล็อคโดยพลการ
        จาก.lock()
        ล็อค()
    อื่น
        ล็อค()
        จาก.lock()
    จาก.ถอน (จำนวนเงิน)
    ที่ฝาก (จำนวนเงิน)
    จาก. ปลดล็อค ()
    เพื่อปลดล็อก()

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

รองรับภาษา

ภาษาการเขียนโปรแกรมแตกต่างกันไปตามการสนับสนุนการซิงโครไนซ์:

  • Adaจัดเตรียมอ็อบเจ็กต์ที่ได้รับการป้องกันซึ่งมีโปรแกรมย่อยหรือรายการที่ได้รับการป้องกันที่มองเห็นได้[6]รวมถึงการนัดพบ [7]
  • มาตรฐาน ISO/IEC CมีAPI การยกเว้นร่วมกัน (ล็อก) มาตรฐานตั้งแต่C11 มาตรฐาน ISO/IEC C++ ปัจจุบัน รองรับการสร้างเธรดตั้งแต่C++ 11 คอมไพเลอร์บางตัวรองรับมาตรฐาน OpenMP และอนุญาตให้ระบุส่วนที่สำคัญโดยใช้Pragmas POSIX pthread API ให้การสนับสนุนการล็อก [8] Visual C++ให้แอตทริบิวต์ของวิธีการที่จะซิงโครไนซ์ แต่นี่เป็นข้อมูลเฉพาะสำหรับวัตถุ COM ในสถาปัตยกรรมWindows และ คอมไพเลอร์Visual C++ [9] synchronize C และ C++ สามารถเข้าถึงคุณลักษณะการล็อกระบบปฏิบัติการดั้งเดิมได้อย่างง่ายดาย
  • C#จัดเตรียมlockคีย์เวิร์ดบนเธรดเพื่อให้แน่ใจว่ามีการเข้าถึงทรัพยากรแบบเอกสิทธิ์เฉพาะบุคคล
  • VB.NETมี คีย์เวิร์ดเช่น คีย์เวิร์ดSyncLockของ C#lock
  • Javaจัดเตรียมคีย์เวิร์ดsynchronizedเพื่อล็อกโค้ดบล็อกเมธอดหรืออ็อบเจ็กต์[10]และไลบรารีที่มีโครงสร้างข้อมูลแบบปลอดภัยพร้อมกัน
  • Objective-Cจัดเตรียมคีย์เวิร์ด@synchronized[11]เพื่อล็อกบล็อกของโค้ด และยังมีคลาส NSLock, [12] NSRecursiveLock, [13]และ NConditionLock [14]พร้อมกับโปรโตคอล NSLocking [15]สำหรับการล็อกด้วย
  • PHPจัดให้มีการล็อกตามไฟล์[16]เช่นเดียวกับMutexคลาสในpthreadsส่วนขยาย [17]
  • Python จัดเตรียม กลไกmutexระดับต่ำ พร้อม Lockคลาสจากthreadingโมดูล [18]
  • มาตรฐาน ISO/IEC Fortran (ISO/IEC 1539-1:2010) ระบุlock_typeประเภทที่ได้รับในโมดูลภายในiso_fortran_envและ คำ สั่งlock/ unlockตั้งแต่Fortran 2008 (19)
  • Ruby จัดเตรียมอ็อบเจ็กต์ mutexระดับต่ำและไม่มีคีย์เวิร์ด (20)
  • สนิมให้โครงสร้างMutex<T>[21 ] [22]
  • แอสเซมบลี x86ให้LOCKคำนำหน้าในการดำเนินการบางอย่างเพื่อรับประกันความเป็นอะตอมของพวกมัน
  • Haskellใช้การล็อกผ่านโครงสร้างข้อมูลที่เปลี่ยนแปลงได้ที่เรียกว่า an MVarซึ่งอาจว่างเปล่าหรือมีค่า ซึ่งโดยทั่วไปแล้วจะเป็นการอ้างอิงถึงทรัพยากร เธรดที่ต้องการใช้ทรัพยากร 'รับ' ค่าของMVarปล่อยว่างไว้ และนำกลับมาเมื่อเสร็จสิ้น ความพยายามที่จะนำทรัพยากรจากMVarผลลัพธ์ที่ว่างเปล่าในการบล็อกเธรดจนกว่าทรัพยากรจะพร้อมใช้งาน [23]นอกจากการล็อกแล้ว ยังมีการใช้งานหน่วยความจำทรานแซคชันซอฟต์แวร์อีกด้วย [24]
  • Go จัดเตรียมอ็อบเจ็กต์ Mutexระดับต่ำ ใน แพ็คเกจ การ ซิงค์ไลบรารีมาตรฐาน [25]สามารถใช้ล็อคบล็อคโค้ดเมธอดหรืออ็อบเจกต์

ดูเพิ่มเติม

อ้างอิง

  1. ^ "คำสั่งล็อก (อ้างอิง C#)" .
  2. ^ "ThreadPoolPriority และ MethodImplAttribute " เอ็มเอสดีเอ็น หน้า ?? . สืบค้นเมื่อ2011-11-22 .
  3. ^ "C# จากมุมมองของนักพัฒนา Java " เก็บถาวรจากต้นฉบับเมื่อ 2013-01-02 สืบค้นเมื่อ2011-11-22 .
  4. ^ "การออกแบบส่วนประกอบชั้นข้อมูลและการส่งผ่านข้อมูลผ่านระดับชั้น " ไมโครซอฟต์ . สิงหาคม 2545 เก็บถาวรจากต้นฉบับเมื่อ 2008-05-08 . สืบค้นเมื่อ2008-05-30 .
  5. เพย์ตัน โจนส์, ไซมอน (2007). “พร้อมกันที่สวยงาม” (PDF) . ในวิลสัน เกร็ก; โอรัม, แอนดี้ (สหพันธ์). รหัสที่สวยงาม: โปรแกรมเมอร์ชั้นนำอธิบายว่าพวกเขาคิดอย่างไร โอเรลลี่.
  6. ^ ISO/IEC 8652:2007. "หน่วยที่ได้รับการคุ้มครองและวัตถุที่ได้รับการคุ้มครอง" . คู่มืออ้างอิง Ada 2005 สืบค้นเมื่อ2010-02-27 . ออบเจ็กต์ที่ได้รับการป้องกันให้การเข้าถึงข้อมูลที่ใช้ร่วมกันผ่านการเรียกใช้การดำเนินการที่ได้รับการป้องกันที่มองเห็นได้ ซึ่งสามารถป้องกันโปรแกรมย่อยหรือรายการที่ได้รับการป้องกัน
  7. ^ ISO/IEC 8652:2007. "ตัวอย่างการทำงานและการซิงโครไนซ์" . คู่มืออ้างอิง Ada 2005 สืบค้นเมื่อ2010-02-27 .
  8. ^ มาร์แชล เดฟ (มีนาคม 2542) "ล็อคการยกเว้นร่วมกัน" . สืบค้นเมื่อ2008-05-30 .
  9. ^ "ซิงโครไนซ์" . msdn.microsoft.com . สืบค้นเมื่อ2008-05-30 .
  10. ^ "การซิงโครไนซ์" . ซันไมโครซิสเต็มส์. สืบค้นเมื่อ2008-05-30 .
  11. ^ "การอ้างอิงเธรดของ Apple" แอปเปิลอิงค์ สืบค้นเมื่อ2009-10-17 .
  12. ^ "อ้างอิง NSLock" . แอปเปิลอิงค์ สืบค้นเมื่อ2009-10-17 .
  13. ^ "อ้างอิง NSRecursiveLock " แอปเปิลอิงค์ สืบค้นเมื่อ2009-10-17 .
  14. ^ "ข้อมูลอ้างอิง NSConditionLock" . แอปเปิลอิงค์ สืบค้นเมื่อ2009-10-17 .
  15. ^ "อ้างอิงโปรโตคอล NSLocking " แอปเปิลอิงค์ สืบค้นเมื่อ2009-10-17 .
  16. ^ "ฝูง" .
  17. ^ "คลาส Mutex" .
  18. ลุนด์, เฟรดริก (กรกฎาคม 2550). "กลไกการซิงโครไนซ์เธรดใน Python " เก็บถาวรจากต้นฉบับเมื่อ 2020-11-01 . สืบค้นเมื่อ2008-05-30 .
  19. ^ จอห์น รีด (2010). "Coarrays ใน Fortran Standard ครั้งต่อไป" (PDF) . สืบค้นเมื่อ2020-02-17 .
  20. ^ "การเขียนโปรแกรมทับทิม: เธรดและกระบวนการ " 2544 . สืบค้นเมื่อ2008-05-30 .
  21. ^ "std::sync::Mutex - Rust" . doc.rust-lang.org . สืบค้นเมื่อ3 พฤศจิกายน 2020 .
  22. ^ "การทำงานพร้อมกันของรัฐที่ใช้ร่วมกัน - ภาษาการเขียนโปรแกรม Rust " doc.rust-lang.org . สืบค้นเมื่อ3 พฤศจิกายน 2020 .
  23. ^ มาร์โลว์, ไซมอน (สิงหาคม 2013). "การทำงานพร้อมกันขั้นพื้นฐาน: เธรดและ MVars" การเขียนโปรแกรมแบบขนานและพร้อม กันใน Haskell โอเรล ลี่ มีเดีย . ISBN 9781449335946.
  24. ^ มาร์โลว์, ไซมอน (สิงหาคม 2013). "ซอฟต์แวร์หน่วยความจำธุรกรรม". การเขียนโปรแกรมแบบขนานและพร้อม กันใน Haskell โอเรล ลี่ มีเดีย . ISBN 9781449335946.
  25. ^ "แพ็คเกจซิงค์ - ซิงค์ - pkg.go.dev " pkg.go.dev _ สืบค้นเมื่อ2021-11-23 .

ลิงค์ภายนอก