Tôi không cần phải chấm dứt chuỗi chính xác, hoặc làm cho nó đáp ứng với lệnh "chấm dứt". Tôi quan tâm đến việc chấm dứt luồng mạnh mẽ bằng cách sử dụng C ++ 11 thuần túy.
Tôi không cần phải chấm dứt chuỗi chính xác, hoặc làm cho nó đáp ứng với lệnh "chấm dứt". Tôi quan tâm đến việc chấm dứt luồng mạnh mẽ bằng cách sử dụng C ++ 11 thuần túy.
Câu trả lời:
Bạn có thể gọi std::terminate()
từ bất kỳ chủ đề nào và chủ đề bạn đang đề cập sẽ kết thúc mạnh mẽ.
Bạn có thể sắp xếp ~thread()
để được thực thi trên đối tượng của luồng đích, mà không cần can thiệp join()
cũng như detach()
vào đối tượng đó. Điều này sẽ có tác dụng tương tự như tùy chọn 1.
Bạn có thể thiết kế một ngoại lệ có hàm hủy để ném ngoại lệ. Và sau đó sắp xếp cho luồng đích để ném ngoại lệ này khi nó bị chấm dứt mạnh mẽ. Phần khó khăn trong phần này là lấy luồng đích để ném ngoại lệ này.
Tùy chọn 1 và 2 không rò rỉ tài nguyên trong quá trình, nhưng chúng chấm dứt mọi luồng.
Tùy chọn 3 có thể sẽ rò rỉ tài nguyên, nhưng hợp tác một phần trong đó luồng đích phải đồng ý ném ngoại lệ.
Không có cách di động nào trong C ++ 11 (mà tôi biết) để không giết một chủ đề trong một chương trình đa luồng (tức là không giết tất cả các luồng). Không có động lực để thiết kế một tính năng như vậy.
A std::thread
có thể có chức năng thành viên này:
native_handle_type native_handle();
Bạn có thể sử dụng chức năng này để gọi một chức năng phụ thuộc vào hệ điều hành để làm những gì bạn muốn. Ví dụ: trên hệ điều hành của Apple, chức năng này tồn tại và native_handle_type
là một pthread_t
. Nếu bạn thành công, bạn có khả năng rò rỉ tài nguyên.
std::terminate
không gọi các hàm hủy tĩnh cũng như không xóa bộ đệm đầu ra, vì vậy thứ tự phát hành tài nguyên không được xác định rõ, bạn cũng không đảm bảo rằng bất kỳ dữ liệu nào của bạn sẽ hiển thị cho người dùng hoặc được ghi vào lưu trữ vĩnh viễn hoặc thậm chí nhất quán và đầy đủ.
exit()
hoặc abort()
để có hiệu lực tổng thể tương tự.
Câu trả lời của @Howard Hinnant vừa chính xác vừa toàn diện. Nhưng nó có thể bị hiểu nhầm nếu đọc quá nhanh, bởi vì std::terminate()
(toàn bộ quá trình) xảy ra có cùng tên với "chấm dứt" mà @AlexanderVX có trong đầu (1 luồng).
Tóm tắt: "chấm dứt 1 luồng + mạnh mẽ (luồng đích không hợp tác) + thuần C ++ 11 = Không thể nào."
std::terminate()
câu trả lời giống như một câu chuyện Djinn tinh nghịch cổ điển; nó hoàn thành mọi thứ trong mong muốn của OP đối với bức thư, mặc dù có lẽ không phải theo ý anh . Sự hài hước ngầm làm tôi mỉm cười. :-)
Câu hỏi này thực sự có bản chất sâu sắc hơn và sự hiểu biết tốt về các khái niệm đa luồng nói chung sẽ cung cấp cho bạn cái nhìn sâu sắc về chủ đề này. Trong thực tế, không có bất kỳ ngôn ngữ hoặc bất kỳ hệ điều hành nào cung cấp cho bạn các phương tiện để chấm dứt luồng không đồng bộ đột ngột mà không có cảnh báo để không sử dụng chúng. Và tất cả các môi trường thực thi này khuyến cáo mạnh mẽ cho nhà phát triển hoặc thậm chí yêu cầu xây dựng các ứng dụng đa luồng trên cơ sở chấm dứt luồng đồng bộ hoặc hợp tác. Lý do cho các quyết định và lời khuyên chung này là tất cả chúng được xây dựng trên cơ sở của cùng một mô hình đa luồng chung.
Chúng ta hãy so sánh các khái niệm đa xử lý và đa luồng để hiểu rõ hơn các ưu điểm và hạn chế của khái niệm thứ hai.
Đa xử lý giả định chia tách toàn bộ môi trường thực thi thành tập hợp các quy trình hoàn toàn biệt lập được kiểm soát bởi hệ điều hành. Quá trình kết hợp và cô lập trạng thái môi trường thực thi bao gồm bộ nhớ cục bộ của quá trình và dữ liệu bên trong nó và tất cả các tài nguyên hệ thống như tệp, ổ cắm, đối tượng đồng bộ hóa. Cô lập là một đặc tính cực kỳ quan trọng của quy trình, bởi vì nó hạn chế sự lan truyền lỗi bởi các đường viền của quy trình. Nói cách khác, không một quy trình nào có thể ảnh hưởng đến tính nhất quán của bất kỳ quy trình nào khác trong hệ thống. Điều này cũng đúng với hành vi xử lý nhưng theo cách ít bị hạn chế và mờ hơn. Trong môi trường như vậy, bất kỳ quá trình nào cũng có thể bị giết trong bất kỳ thời điểm "tùy ý" nào, bởi vì trước hết mỗi quy trình được cách ly, thứ hai,
Ngược lại, đa luồng giả định chạy nhiều luồng trong cùng một tiến trình. Nhưng tất cả các luồng này được chia sẻ cùng một hộp cách ly và không có bất kỳ điều khiển hệ điều hành nào về trạng thái bên trong của quá trình. Kết quả là bất kỳ luồng nào cũng có thể thay đổi trạng thái quy trình toàn cầu cũng như làm hỏng nó. Đồng thời, các điểm trong đó trạng thái của luồng được biết là an toàn để giết một luồng hoàn toàn phụ thuộc vào logic ứng dụng và không được biết đến đối với hệ điều hành cũng như thời gian chạy ngôn ngữ lập trình. Kết quả là chấm dứt luồng tại thời điểm tùy ý có nghĩa là giết nó tại điểm tùy ý của đường dẫn thực thi của nó và có thể dễ dàng dẫn đến hỏng dữ liệu trên toàn quy trình, bộ nhớ và xử lý rò rỉ,
Do đó, cách tiếp cận phổ biến là buộc các nhà phát triển thực hiện chấm dứt luồng đồng bộ hoặc hợp tác, trong đó một luồng có thể yêu cầu chấm dứt luồng khác và luồng khác ở điểm được xác định rõ có thể kiểm tra yêu cầu này và bắt đầu quy trình tắt từ trạng thái được xác định rõ với việc phát hành tất cả các tài nguyên trên toàn hệ thống và tài nguyên trên toàn quy trình theo cách an toàn và nhất quán.
Mẹo sử dụng chức năng phụ thuộc hệ điều hành để chấm dứt luồng C ++:
std::thread::native_handle()
chỉ có thể nhận loại xử lý riêng hợp lệ của luồng trước khi gọi join()
hoặc detach()
. Sau đó, native_handle()
trả về 0 - pthread_cancel()
sẽ coredump.
Để gọi hiệu quả chức năng chấm dứt luồng gốc (ví dụ pthread_cancel()
), bạn cần lưu xử lý gốc trước khi gọi std::thread::join()
hoặc std::thread::detach()
. Vì vậy, terminator gốc của bạn luôn có một xử lý gốc hợp lệ để sử dụng.
Giải thích thêm xin vui lòng tham khảo: http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread .
Tôi đoán rằng các chủ đề cần phải bị giết là trong bất kỳ chế độ chờ đợi, hoặc làm một số công việc nặng. Tôi sẽ đề nghị sử dụng một cách "ngây thơ".
Xác định một số boolean toàn cầu:
std::atomic_bool stop_thread_1 = false;
Đặt mã sau (hoặc tương tự) vào một số điểm chính, theo cách nó sẽ khiến tất cả các chức năng trong ngăn xếp cuộc gọi trở lại cho đến khi chuỗi kết thúc tự nhiên:
if (stop_thread_1)
return;
Sau đó để dừng luồng từ luồng khác (chính):
stop_thread_1 = true;
thread1.join ();
stop_thread_1 = false; //(for next time. this can be when starting the thread instead)