Saya tidak perlu menghentikan utas dengan benar, atau membuatnya menanggapi perintah "terminasi". Saya tertarik untuk menghentikan utas dengan paksa menggunakan C ++ 11 murni.
Saya tidak perlu menghentikan utas dengan benar, atau membuatnya menanggapi perintah "terminasi". Saya tertarik untuk menghentikan utas dengan paksa menggunakan C ++ 11 murni.
Jawaban:
Anda dapat menelepon std::terminate()
dari utas apa pun dan utas yang Anda maksud akan dengan paksa berakhir.
Anda bisa mengatur ~thread()
agar dieksekusi pada objek utas target, tanpa campur tangan join()
atau detach()
pada objek itu. Ini akan memiliki efek yang sama dengan opsi 1.
Anda bisa mendesain pengecualian yang memiliki destruktor yang melempar pengecualian. Dan kemudian mengatur utas utas untuk melemparkan pengecualian ini ketika akan diberhentikan dengan paksa. Bagian yang sulit dalam hal ini adalah mendapatkan utas target untuk membuang pengecualian ini.
Opsi 1 dan 2 tidak membocorkan sumber daya intra-proses, tetapi mereka mengakhiri setiap utas.
Opsi 3 mungkin akan membocorkan sumber daya, tetapi sebagian kooperatif karena utas target harus setuju untuk melemparkan pengecualian.
Tidak ada cara portabel di C ++ 11 (yang saya tahu) untuk secara non-kooperatif membunuh satu utas dalam program multi-utas (yaitu tanpa membunuh semua utas). Tidak ada motivasi untuk mendesain fitur seperti itu.
A std::thread
mungkin memiliki fungsi anggota ini:
native_handle_type native_handle();
Anda mungkin dapat menggunakan ini untuk memanggil fungsi yang bergantung pada OS untuk melakukan apa yang Anda inginkan. Misalnya pada OS Apple, fungsi ini ada dan native_handle_type
a pthread_t
. Jika Anda berhasil, Anda kemungkinan akan membocorkan sumber daya.
std::terminate
tidak memanggil destruktor statis juga tidak menyiram buffer output, sehingga urutan sumber daya yang dirilis tidak terdefinisi dengan baik, Anda juga tidak memiliki jaminan bahwa data Anda dapat dilihat oleh pengguna atau ditulis ke toko permanen, atau bahkan konsisten dan lengkap.
exit()
atau abort()
dengan efek keseluruhan yang sama.
Jawaban @Howard Hinnant benar dan komprehensif. Tetapi mungkin disalahpahami jika dibaca terlalu cepat, karena std::terminate()
(seluruh proses) kebetulan memiliki nama yang sama dengan "terminating" yang ada dalam pikiran @AlexanderVX (1 utas).
Ringkasan: "terminasi 1 utas + secara paksa (utas target tidak bekerja sama) + murni C ++ 11 = Tidak mungkin."
std::terminate()
jawabannya seperti kisah Djinn nakal klasik; itu memenuhi semua keinginan OP untuk surat itu, meskipun mungkin tidak dengan cara yang dia maksudkan . Humor yang bersahaja membuatku tersenyum. :-)
Pertanyaan ini sebenarnya memiliki sifat yang lebih dalam dan pemahaman yang baik tentang konsep multithreading secara umum akan memberi Anda wawasan tentang topik ini. Sebenarnya tidak ada bahasa atau sistem operasi apa pun yang memberikan Anda fasilitas untuk penghentian utas secara tiba-tiba tanpa peringatan untuk tidak menggunakannya. Dan semua lingkungan eksekusi ini sangat menyarankan pengembang atau bahkan memerlukan membangun aplikasi multithreading atas dasar pemutusan thread koperasi atau sinkron. Alasan untuk keputusan dan saran umum ini adalah bahwa semua itu dibangun di atas dasar model multithreading umum yang sama.
Mari kita bandingkan konsep multiprocessing dan multithreading untuk lebih memahami kelebihan dan keterbatasan yang kedua.
Multiprocessing mengasumsikan pemisahan seluruh lingkungan eksekusi ke dalam set proses yang sepenuhnya terisolasi yang dikendalikan oleh sistem operasi. Proses menggabungkan dan mengisolasi keadaan lingkungan eksekusi termasuk memori lokal dari proses dan data di dalamnya dan semua sumber daya sistem seperti file, soket, objek sinkronisasi. Isolasi adalah karakteristik yang sangat penting dari proses, karena membatasi penyebaran kesalahan oleh batas-batas proses. Dengan kata lain, tidak ada satu proses yang dapat mempengaruhi konsistensi proses lain dalam sistem. Hal yang sama berlaku untuk perilaku proses tetapi dengan cara yang tidak terlalu terbatas dan lebih kabur. Dalam lingkungan seperti itu setiap proses dapat dibunuh dalam momen "sewenang-wenang", karena pertama setiap proses diisolasi, kedua,
Sebaliknya, multithreading mengasumsikan menjalankan banyak utas dalam proses yang sama. Tetapi semua utas ini memiliki kotak isolasi yang sama dan tidak ada kontrol sistem operasi dari kondisi internal proses. Akibatnya setiap utas dapat mengubah status proses global dan juga merusaknya. Pada saat yang sama titik-titik di mana keadaan utas dikenal aman untuk mematikan utas sepenuhnya tergantung pada logika aplikasi dan tidak dikenal baik untuk sistem operasi maupun untuk runtime bahasa pemrograman. Sebagai akibatnya, penghentian utas pada saat yang sewenang-wenang berarti membunuhnya pada titik sewenang-wenang dari jalur pelaksanaannya dan dapat dengan mudah mengarah pada proses korupsi data yang luas, memori dan menangani kebocoran,
Karena ini, pendekatan umum adalah memaksa pengembang untuk menerapkan penghentian utas sinkron atau kooperatif, di mana satu utas dapat meminta penghentian utas lainnya dan utas lainnya dalam titik yang ditentukan dengan baik dapat memeriksa permintaan ini dan memulai prosedur penutupan dari kondisi yang ditentukan dengan baik dengan melepaskan semua sumber daya seluruh sistem global dan sumber daya seluruh proses lokal dengan cara yang aman dan konsisten.
Kiat menggunakan fungsi yang bergantung pada OS untuk mengakhiri utas C ++:
std::thread::native_handle()
hanya bisa mendapatkan jenis pegangan asli yang valid sebelum menelepon join()
atau detach()
. Setelah itu, native_handle()
mengembalikan 0 - pthread_cancel()
akan coredump.
Untuk secara efektif memanggil fungsi penghentian utas asli (mis. pthread_cancel()
), Anda perlu menyimpan gagang asli sebelum menelepon std::thread::join()
atau std::thread::detach()
. Sehingga terminator asli Anda selalu memiliki pegangan asli yang valid untuk digunakan.
Penjelasan lebih lanjut silakan merujuk ke: http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread .
Saya kira utas yang perlu dibunuh adalah apakah dalam mode menunggu apa pun, atau melakukan pekerjaan berat. Saya akan menyarankan menggunakan cara "naif".
Tetapkan beberapa boolean global:
std::atomic_bool stop_thread_1 = false;
Masukkan kode berikut (atau serupa) di beberapa titik kunci, dengan cara itu akan menyebabkan semua fungsi di tumpukan panggilan kembali sampai utas secara alami berakhir:
if (stop_thread_1)
return;
Kemudian untuk menghentikan utas dari utas lain (utama):
stop_thread_1 = true;
thread1.join ();
stop_thread_1 = false; //(for next time. this can be when starting the thread instead)