Saya mendapatkan kesalahan C ++ dengan threading:
terminate called without an active exception
Aborted
Ini kodenya:
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
template<typename TYPE>
class blocking_stream
{
public:
blocking_stream(size_t max_buffer_size_)
: max_buffer_size(max_buffer_size_)
{
}
//PUSH data into the buffer
blocking_stream &operator<<(TYPE &other)
{
std::unique_lock<std::mutex> mtx_lock(mtx);
while(buffer.size()>=max_buffer_size)
stop_if_full.wait(mtx_lock);
buffer.push(std::move(other));
mtx_lock.unlock();
stop_if_empty.notify_one();
return *this;
}
//POP data out of the buffer
blocking_stream &operator>>(TYPE &other)
{
std::unique_lock<std::mutex> mtx_lock(mtx);
while(buffer.empty())
stop_if_empty.wait(mtx_lock);
other.swap(buffer.front());
buffer.pop();
mtx_lock.unlock();
stop_if_full.notify_one();
return *this;
}
private:
size_t max_buffer_size;
std::queue<TYPE> buffer;
std::mutex mtx;
std::condition_variable stop_if_empty,
stop_if_full;
bool eof;
};
Saya membuat model kode saya di sekitar contoh ini: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html
Apa yang saya lakukan salah dan bagaimana cara memperbaiki kesalahan tersebut?
c++
multithreading
deadlock
c++11
111111
sumber
sumber
join
memasukkan semua utas Anda dalam program utama Anda?Jawaban:
Saat objek utas keluar dari ruang lingkup dan berada dalam status dapat digabungkan, program dihentikan. Komite Standar memiliki dua opsi lain untuk penghancur utas yang dapat disambung. Itu bisa bergabung secara diam-diam - tetapi bergabung mungkin tidak akan pernah kembali jika utas macet. Atau bisa juga melepaskan utas (utas yang terlepas tidak dapat digabungkan). Namun, utas yang terlepas sangat rumit, karena mereka mungkin bertahan hingga akhir program dan mengacaukan pelepasan sumber daya. Jadi jika Anda tidak ingin menghentikan program Anda, pastikan Anda bergabung (atau melepaskan) setiap utas.
sumber
std::async
? Bagaimana Anda menggabungkan / melepaskan utas apa pun yang mungkin dibuat di sana? Tampaknya menunggu di masa depan yang dihasilkan tidak akan cukup, karena ini mengatakan bahwa utas bisa "berpotensi dari kumpulan utas", dan penantian masa depan () tidak benar-benar menyiratkan penghentian utas di kumpulan (dan itu tidak akan lagian tidak masuk akal untuk kumpulan benang yang waras).std::jthread
akan memanggil.join()
destruktor (karena keluar dari ruang lingkup). Yang secara pribadi saya lebih suka karena mengikuti RAII dengan lebih baik.Bagaimana cara mereproduksi kesalahan itu:
#include <iostream> #include <stdlib.h> #include <string> #include <thread> using namespace std; void task1(std::string msg){ cout << "task1 says: " << msg; } int main() { std::thread t1(task1, "hello"); return 0; }
Kompilasi dan jalankan:
el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11 el@defiant ~/foo4/39_threading $ ./s terminate called without an active exception Aborted (core dumped)
Anda mendapatkan kesalahan itu karena Anda tidak bergabung atau melepaskan utas Anda.
Salah satu cara untuk memperbaikinya, gabung dengan utas seperti ini:
#include <iostream> #include <stdlib.h> #include <string> #include <thread> using namespace std; void task1(std::string msg){ cout << "task1 says: " << msg; } int main() { std::thread t1(task1, "hello"); t1.join(); return 0; }
Kemudian kompilasi dan jalankan:
el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11 el@defiant ~/foo4/39_threading $ ./s task1 says: hello
Cara lain untuk memperbaikinya, lepaskan seperti ini:
#include <iostream> #include <stdlib.h> #include <string> #include <unistd.h> #include <thread> using namespace std; void task1(std::string msg){ cout << "task1 says: " << msg; } int main() { { std::thread t1(task1, "hello"); t1.detach(); } //thread handle is destroyed here, as goes out of scope! usleep(1000000); //wait so that hello can be printed. }
Kompilasi dan jalankan:
el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11 el@defiant ~/foo4/39_threading $ ./s task1 says: hello
Baca tentang melepaskan utas C ++ dan bergabung dengan utas C ++.
sumber
Eric Leschinski dan Bartosz Milewski telah memberikan jawabannya. Di sini, saya akan mencoba menyajikannya dengan cara yang lebih ramah pemula.
Setelah utas dimulai dalam suatu lingkup (yang berjalan sendiri pada utas), seseorang harus secara eksplisit memastikan salah satu hal berikut terjadi sebelum utas keluar dari cakupan:
Perhatikan, pada saat utas digabungkan atau dilepaskan, utas mungkin telah selesai dijalankan. Masih salah satu dari dua operasi tersebut harus dilakukan secara eksplisit.
sumber
Selama program Anda mati, maka tanpa melepaskan atau bergabung dengan utas, kesalahan ini akan terjadi. Tanpa melepaskan dan menggabungkan utas, Anda harus memberikan putaran tanpa akhir setelah membuat utas.
int main(){ std::thread t(thread,1); while(1){} //t.detach(); return 0;}
Menarik juga bahwa, setelah tidur atau berputar, utas dapat dilepas atau digabungkan. Selain itu dengan cara ini anda tidak mendapatkan error ini.
Contoh di bawah ini juga menunjukkan bahwa, thread ketiga tidak dapat melakukan tugasnya sebelum main die. Tapi kesalahan ini tidak bisa terjadi juga, selama Anda melepaskan kode di suatu tempat. Utas ketiga tidur selama 8 detik tetapi utas utama akan mati dalam 5 detik.
void thread(int n) {std::this_thread::sleep_for (std::chrono::seconds(n));} int main() { std::cout << "Start main\n"; std::thread t(thread,1); std::thread t2(thread,3); std::thread t3(thread,8); sleep(5); t.detach(); t2.detach(); t3.detach(); return 0;}
sumber
tahun, utas harus join (). saat keluar utama
sumber
Pertama, Anda menentukan utas. Dan jika Anda tidak pernah memanggil join () atau detach () sebelum memanggil penghancur thread, program akan dibatalkan.
Sebagai berikut, memanggil destruktor thread tanpa terlebih dahulu memanggil join (menunggu sampai selesai) atau detach dijamin akan segera memanggil std :: terminate dan mengakhiri program.
sumber