ฉันไม่จำเป็นต้องยุติเธรดอย่างถูกต้องหรือทำให้มันตอบสนองต่อคำสั่ง "ยุติ" ฉันสนใจที่จะยุติเธรดโดยใช้ C ++ 11 ล้วนๆ
ฉันไม่จำเป็นต้องยุติเธรดอย่างถูกต้องหรือทำให้มันตอบสนองต่อคำสั่ง "ยุติ" ฉันสนใจที่จะยุติเธรดโดยใช้ C ++ 11 ล้วนๆ
คำตอบ:
คุณสามารถโทรstd::terminate()
จากเธรดใดก็ได้และเธรดที่คุณอ้างถึงจะสิ้นสุดลงอย่างมีผล
คุณสามารถจัดเตรียม~thread()
ให้ดำเนินการกับอ็อบเจ็กต์ของเธรดเป้าหมายโดยไม่มีการแทรกแซงjoin()
หรือdetach()
บนอ็อบเจ็กต์นั้น สิ่งนี้จะมีผลเช่นเดียวกับตัวเลือกที่ 1
คุณสามารถออกแบบข้อยกเว้นซึ่งมีตัวทำลายซึ่งทำให้เกิดข้อยกเว้น จากนั้นจัดให้เธรดเป้าหมายโยนข้อยกเว้นนี้เมื่อจำเป็นต้องยุติอย่างจริงจัง ส่วนที่ยุ่งยากในส่วนนี้คือการทำให้เธรดเป้าหมายโยนข้อยกเว้นนี้
ตัวเลือก 1 และ 2 จะไม่รั่วไหลทรัพยากรภายในกระบวนการ แต่จะยุติทุกเธรด
ตัวเลือกที่ 3 อาจทำให้ทรัพยากรรั่วไหล แต่บางส่วนได้รับความร่วมมือในการที่เธรดเป้าหมายต้องยินยอมที่จะทิ้งข้อยกเว้น
ไม่มีวิธีแบบพกพาใน C ++ 11 (ที่ฉันทราบ) ในการฆ่าเธรดเดี่ยวแบบไม่ร่วมมือกันในโปรแกรมมัลติเธรด (กล่าวคือโดยไม่ต้องฆ่าเธรดทั้งหมด) ไม่มีแรงจูงใจในการออกแบบคุณลักษณะดังกล่าว
A std::thread
อาจมีฟังก์ชันสมาชิกนี้:
native_handle_type native_handle();
คุณอาจสามารถใช้สิ่งนี้เพื่อเรียกใช้ฟังก์ชันที่ขึ้นกับระบบปฏิบัติการเพื่อทำสิ่งที่คุณต้องการ ตัวอย่างเช่นในระบบปฏิบัติการของ Apple มีฟังก์ชันนี้อยู่และnative_handle_type
เป็นไฟล์pthread_t
. หากคุณประสบความสำเร็จคุณมีแนวโน้มที่จะทำให้ทรัพยากรรั่วไหล
std::terminate
ไม่เรียกตัวทำลายแบบคงที่หรือไม่ล้างบัฟเฟอร์เอาต์พุตดังนั้นลำดับการปล่อยทรัพยากรจึงไม่ได้กำหนดไว้อย่างชัดเจนและคุณไม่มีการรับประกันว่าข้อมูลใด ๆ ของคุณจะปรากฏแก่ผู้ใช้หรือเขียนลงในที่จัดเก็บถาวรหรือแม้กระทั่ง สอดคล้องและสมบูรณ์
exit()
หรือเอabort()
ฟเฟกต์โดยรวมเดียวกัน
คำตอบของ @Howard Hinnant ทั้งถูกต้องและครอบคลุม แต่อาจเข้าใจผิดหากอ่านเร็วเกินไปเนื่องจากstd::terminate()
(กระบวนการทั้งหมด) มีชื่อเดียวกับ "การยุติ" ที่ @AlexanderVX มีอยู่ในใจ (1 เธรด)
สรุป: "ยุติ 1 เธรด + อย่างมีประสิทธิภาพ (เธรดเป้าหมายไม่ให้ความร่วมมือ) + C ++ บริสุทธิ์ 11 = ไม่มีทาง"
std::terminate()
คำตอบก็เหมือนกับเรื่องราวของจินน์ที่ซุกซนแบบคลาสสิก มันตอบสนองทุกสิ่งในความปรารถนาของ OP ที่มีต่อจดหมายแม้ว่าอาจจะไม่ได้เป็นไปในทางที่เขาหมายถึงก็ตาม อารมณ์ขันที่พูดน้อยทำให้ฉันยิ้ม :-)
คำถามนี้มีลักษณะที่ลึกซึ้งกว่าและความเข้าใจที่ดีเกี่ยวกับแนวคิดมัลติเธรดโดยทั่วไปจะช่วยให้คุณมีความเข้าใจเกี่ยวกับหัวข้อนี้ ในความเป็นจริงไม่มีภาษาหรือระบบปฏิบัติการใด ๆ ที่ให้สิ่งอำนวยความสะดวกแก่คุณสำหรับการยุติเธรดแบบอะซิงโครนัสทันทีโดยไม่มีคำเตือนว่าจะไม่ใช้งาน และสภาพแวดล้อมการดำเนินการทั้งหมดเหล่านี้ขอแนะนำอย่างยิ่งให้นักพัฒนาหรือแม้แต่ต้องการสร้างแอปพลิเคชันมัลติเธรดบนฐานของการยุติเธรดแบบร่วมมือหรือแบบซิงโครนัส เหตุผลสำหรับการตัดสินใจและคำแนะนำทั่วไปนี้คือทั้งหมดนี้สร้างขึ้นจากพื้นฐานของโมเดลมัลติเธรดทั่วไปเดียวกัน
ลองเปรียบเทียบแนวคิดหลายกระบวนการและมัลติเธรดเพื่อทำความเข้าใจข้อดีและข้อ จำกัด ของแนวคิดที่สองให้ดีขึ้น
การประมวลผลหลายขั้นตอนจะถือว่าการแบ่งสภาพแวดล้อมการดำเนินการทั้งหมดออกเป็นชุดของกระบวนการที่แยกออกจากกันโดยสิ้นเชิงซึ่งควบคุมโดยระบบปฏิบัติการ กระบวนการรวมและแยกสถานะสภาพแวดล้อมการดำเนินการรวมถึงหน่วยความจำภายในของกระบวนการและข้อมูลภายในและทรัพยากรระบบทั้งหมดเช่นไฟล์ซ็อกเก็ตอ็อบเจ็กต์การซิงโครไนซ์ การแยกเป็นลักษณะที่สำคัญอย่างยิ่งของกระบวนการเนื่องจากเป็นการ จำกัด การแพร่กระจายความผิดพลาดโดยพรมแดนของกระบวนการ กล่าวอีกนัยหนึ่งคือไม่มีกระบวนการใดที่สามารถส่งผลต่อความสอดคล้องของกระบวนการอื่นในระบบได้ เช่นเดียวกับพฤติกรรมของกระบวนการ แต่ในวิธีที่ จำกัด น้อยกว่าและเบลอมากขึ้น ในสภาพแวดล้อมเช่นนี้กระบวนการใด ๆ สามารถถูกฆ่าได้ในช่วงเวลา "ตามอำเภอใจ" เพราะประการแรกแต่ละกระบวนการถูกแยกออกจากกันประการที่สอง
ในทางตรงกันข้ามการใช้หลายเธรดจะถือว่าการรันหลายเธรดในกระบวนการเดียวกัน แต่เธรดทั้งหมดนี้ใช้กล่องแยกเดียวกันและไม่มีการควบคุมระบบปฏิบัติการใด ๆ ของสถานะภายในของกระบวนการ ด้วยเหตุนี้เธรดใด ๆ จึงสามารถเปลี่ยนสถานะกระบวนการส่วนกลางรวมทั้งเสียหายได้ ในขณะเดียวกันจุดที่สถานะของเธรดเป็นที่ทราบกันดีว่าปลอดภัยในการฆ่าเธรดโดยสมบูรณ์นั้นขึ้นอยู่กับตรรกะของแอปพลิเคชันและไม่เป็นที่รู้จักสำหรับระบบปฏิบัติการหรือรันไทม์ภาษาโปรแกรม ผลที่ตามมาคือการยุติเธรดในช่วงเวลาโดยพลการหมายถึงการฆ่ามัน ณ จุดใดจุดหนึ่งของเส้นทางการดำเนินการและอาจนำไปสู่ความเสียหายของข้อมูลทั้งกระบวนการหน่วยความจำและการจัดการการรั่วไหลได้อย่างง่ายดาย
ด้วยเหตุนี้วิธีการทั่วไปคือการบังคับให้นักพัฒนาใช้การยุติเธรดแบบซิงโครนัสหรือการทำงานร่วมกันโดยที่เธรดหนึ่งสามารถร้องขอการยุติเธรดอื่นและเธรดอื่นในจุดที่กำหนดไว้อย่างดีสามารถตรวจสอบคำร้องขอนี้และเริ่มขั้นตอนการปิดระบบจากสถานะที่กำหนดไว้อย่างดี ด้วยการปล่อยทรัพยากรทั่วทั้งระบบและทรัพยากรทั้งกระบวนการในพื้นที่อย่างปลอดภัยและสม่ำเสมอ
เคล็ดลับในการใช้ฟังก์ชันที่ขึ้นกับระบบปฏิบัติการเพื่อยุติเธรด C ++:
std::thread::native_handle()
สามารถได้รับถูกต้องชนิดจับพื้นเมืองของเธรดก่อนที่จะเรียกหรือjoin()
detach()
หลังจากนั้นnative_handle()
ส่งกลับ 0 - pthread_cancel()
จะ coredump
เพื่อประสิทธิภาพในการเรียกใช้ฟังก์ชันการเลิกจ้างด้ายพื้นเมือง (เช่นpthread_cancel()
), คุณจำเป็นต้องบันทึกจับพื้นเมืองก่อนที่จะเรียกหรือstd::thread::join()
std::thread::detach()
เพื่อให้เทอร์มิเนเตอร์เนทีฟของคุณมีแฮนเดิลเนทีฟที่ใช้ได้เสมอ
คำอธิบายเพิ่มเติมโปรดดูที่: http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread
ฉันเดาว่าเธรดที่ต้องฆ่าไม่ว่าจะอยู่ในโหมดรอแบบใดก็ตามหรือทำงานหนัก ฉันขอแนะนำให้ใช้วิธีที่ "ไร้เดียงสา"
กำหนดบูลีนส่วนกลางบางส่วน:
std::atomic_bool stop_thread_1 = false;
ใส่รหัสต่อไปนี้ (หรือที่คล้ายกัน) ในประเด็นสำคัญหลาย ๆ จุดในลักษณะที่จะทำให้ฟังก์ชันทั้งหมดใน call stack กลับมาจนกว่าเธรดจะสิ้นสุดลงตามธรรมชาติ:
if (stop_thread_1)
return;
จากนั้นเพื่อหยุดเธรดจากเธรด (หลัก) อื่น:
stop_thread_1 = true;
thread1.join ();
stop_thread_1 = false; //(for next time. this can be when starting the thread instead)