Kadang-kadang saya harus menggunakan std::thread
untuk mempercepat aplikasi saya. Saya juga tahu join()
menunggu sampai utas selesai. Ini mudah dimengerti, tetapi apa perbedaan antara menelepon detach()
dan tidak menelepon?
Saya pikir tanpa detach()
, metode utas akan bekerja menggunakan utas secara mandiri.
Tidak melepaskan:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called without detach");
});
//some code here
}
Memanggil dengan melepaskan:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called with detach");
});
t.detach();
//some code here
}
std
danboost
utas memilikidetach
danjoin
dimodelkan secara dekat setelah utas POSIX.Jawaban:
Di destruktor dari
std::thread
,std::terminate
dipanggil jika:t.join()
)t.detach()
)Jadi, Anda harus selalu salah satu
join
ataudetach
utas sebelum aliran eksekusi mencapai destruktor.Ketika sebuah program berhenti (mis.,
main
Mengembalikan) sisa utas yang terlepas yang dieksekusi di latar belakang tidak menunggu; sebagai gantinya, eksekusinya ditangguhkan dan objek lokal thread mereka dihancurkan.Yang terpenting, ini berarti bahwa tumpukan utas tersebut tidak dibatalkan dan dengan demikian beberapa perusak tidak dieksekusi. Bergantung pada tindakan yang seharusnya dilakukan oleh para destruktor tersebut, ini mungkin situasi yang seburuk jika program telah rusak atau telah terbunuh. Mudah-mudahan OS akan melepaskan kunci pada file, dll ... tetapi Anda bisa merusak memori bersama, file setengah tertulis, dan sejenisnya.
Jadi, haruskah Anda menggunakan
join
ataudetach
?join
detach
sumber
Anda harus memanggil
detach
jika Anda tidak akan menunggu utas selesaijoin
tetapi utas akan terus berjalan sampai selesai dan kemudian menghentikannya tanpa harus menunggu utas utama secara khusus.detach
pada dasarnya akan mengeluarkan sumber daya yang dibutuhkan untuk dapat mengimplementasikanjoin
.Ini adalah kesalahan fatal jika objek utas mengakhiri hidupnya dan tidak
join
juga tidakdetach
dipanggil; dalam halterminate
ini dipanggil.sumber
Jika Anda melepaskan utas, artinya Anda tidak perlu melepaskannya
join()
sebelum keluarmain()
.Perpustakaan utas sebenarnya akan menunggu setiap utas seperti itu di bawah-utama , tetapi Anda tidak perlu peduli tentang itu.
detach()
berguna terutama saat Anda memiliki tugas yang harus diselesaikan di latar belakang, tetapi Anda tidak peduli dengan pelaksanaannya. Ini biasanya terjadi pada beberapa perpustakaan. Mereka mungkin secara diam-diam membuat thread pekerja latar belakang dan melepaskannya sehingga Anda tidak akan menyadarinya.sumber
Jawaban ini ditujukan untuk menjawab pertanyaan di judul, daripada menjelaskan perbedaan antara
join
dandetach
. Jadi kapan sebaiknyastd::thread::detach
digunakan?Dalam kode C ++ yang dipelihara dengan baik
std::thread::detach
tidak boleh digunakan sama sekali. Programmer harus memastikan bahwa semua utas yang dibuat keluar dengan anggun dan melepaskan semua sumber daya yang diperoleh dan melakukan tindakan pembersihan lain yang diperlukan. Ini menyiratkan bahwa menyerahkan kepemilikan utas dengan memintadetach
bukanlah suatu pilihan dan oleh karena itujoin
harus digunakan dalam semua skenario.Namun beberapa aplikasi bergantung pada API lama dan seringkali tidak dirancang dengan baik dan didukung yang mungkin berisi fungsi pemblokiran tanpa batas. Memindahkan pemanggilan fungsi ini ke utas khusus untuk menghindari pemblokiran hal-hal lain adalah praktik umum. Tidak ada cara untuk membuat utas seperti itu keluar dengan anggun sehingga penggunaan
join
hanya akan mengarah ke pemblokiran utas utama. Itu adalah situasi ketika menggunakandetach
akan menjadi alternatif yang kurang jahat, katakanlah, mengalokasikanthread
objek dengan durasi penyimpanan dinamis dan kemudian dengan sengaja membocorkannya.#include <LegacyApi.hpp> #include <thread> auto LegacyApiThreadEntry(void) { auto result{NastyBlockingFunction()}; // do something... } int main() { ::std::thread legacy_api_thread{&LegacyApiThreadEntry}; // do something... legacy_api_thread.detach(); return 0; }
sumber
std::getline
akan memblokir tanpa batasMenurut cppreference.com :
Sebagai contoh:
std::thread my_thread([&](){XXXX}); my_thread.detach();
Perhatikan variabel lokal:,
my_thread
sementara masa pakaimy_thread
berakhir, destruktor daristd::thread
akan dipanggil, danstd::terminate()
akan dipanggil di dalam destruktor.Tetapi jika Anda menggunakan
detach()
, Anda tidak boleh menggunakanmy_thread
lagi, bahkan jika masa pakaimy_thread
sudah berakhir, tidak ada yang akan terjadi pada utas baru.sumber
&
dalam tangkapan lambda, Anda menggunakan variabel lingkup terlampir dengan referensi - jadi Anda sebaiknya memastikan masa pakai referensi Anda lebih lama dari masa pakai utas Anda.