3.1 วัตถุที่ใช้งานอยู่

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

รุ่นประยุกต์:

วัตถุที่ใช้งานอยู่

รุ่นคลาสสิก:

วัตถุที่ใช้งาน 2

เทมเพลตนี้มีหกองค์ประกอบ:

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

3.2 ล็อค

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

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

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

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

รูปแบบการล็อค

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

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

รูปแบบการล็อค 2

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

3.3 จอภาพ

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

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

จอภาพประกอบด้วย:

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

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

นี่คือวิธีที่ ตัวดำเนินการ ซิงโครไนซ์ ทำงานใน Java ด้วยwait()and วิธี notify()การ

3.4 ตรวจสอบการล็อกสองครั้ง

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

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

//Double-Checked Locking
public final class Singleton {
private static Singleton instance; //Don't forget volatile modifier

public static Singleton getInstance() {
     if (instance == null) {                //Read

         synchronized (Singleton.class) {    //
             if (instance == null) {         //Read Write
                 instance = new Singleton(); //
             }
         }
     }
 }

จะสร้าง singleton object ในสภาวะแวดล้อมแบบ thread-safe ได้อย่างไร?

public static Singleton getInstance() {
   if (instance == null)
    instance = new Singleton();
}

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

public static Singleton getInstance() {
    synchronized (Singleton.class) {
        if (instance == null)
        instance = new Singleton();
    }
}

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

public static Singleton getInstance() {
     if (instance != null)
        return instance;

    synchronized (Singleton.class) {
        if (instance == null)
        instance = new Singleton();
    }
}

ในบางภาษาและ/หรือในบางเครื่อง ไม่สามารถใช้รูปแบบนี้ได้อย่างปลอดภัย ดังนั้นบางครั้งจึงเรียกว่ารูปแบบต่อต้าน คุณลักษณะดังกล่าวนำไปสู่การปรากฏของความสัมพันธ์ลำดับที่เข้มงวด "เกิดขึ้นก่อน" ใน Java Memory Model และ C++ Memory Model

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

3.5 ตัวกำหนดตารางเวลา

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