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