Rumah > Artikel > pembangunan bahagian belakang > Mengapa Saya Mendapat Segfaults Apabila Menggunakan Pembolehubah Keadaan untuk Menyemak Baris Gilir Kosong dalam C?
Baris gilir selamat benang C 11: Kekeliruan terhadap penggunaan pembolehubah keadaan
Dalam kod anda, anda melaksanakan baris gilir selamat benang menggunakan mutex dan pembolehubah keadaan. Walau bagaimanapun, anda menghadapi segfault sekali-sekala dalam blok kod yang dikawal oleh pembolehubah keadaan. Secara khususnya, anda dapati bahawa segfaults berlaku apabila baris gilir kosong, yang kelihatan berlawanan dengan intuitif kerana pembolehubah keadaan bertujuan untuk menandakan ketersediaan item baharu dalam baris gilir.
Penggunaan Pembolehubah Keadaan Salah
Salah faham anda berpunca daripada penggunaan pembolehubah keadaan yang salah. Tujuan pembolehubah keadaan adalah untuk menandakan perubahan dalam keadaan dikongsi, di mana urutan lain kemudiannya boleh bertindak balas terhadap perubahan ini. Walau bagaimanapun, dalam kod anda, anda menggunakan pembolehubah keadaan untuk menunggu keadaan tertentu (baris gilir kosong) menjadi palsu. Ini tidak betul kerana apabila keadaan menjadi palsu (iaitu, baris gilir tidak lagi kosong), benang akan terjaga, tetapi ia tidak dijamin bahawa syarat itu kekal palsu (iaitu, baris gilir mungkin kosong semula dalam masa yang sama) .
Penggunaan Pembolehubah Keadaan Yang Betul
Cara yang betul untuk menggunakan pembolehubah keadaan adalah dengan mempunyai gelung yang menyemak keadaan (dalam kes ini, sama ada baris gilir kosong ) dan memasuki keadaan menunggu jika syarat tidak dipenuhi. Apabila keadaan diisyaratkan, benang akan bangun, tetapi ia akan segera menyemak semula keadaan sebelum meneruskan. Ini memastikan bahawa utas hanya melakukan operasi yang diingini jika keadaan masih benar apabila bangun.
Pelaksanaan Alternatif
Berikut ialah pelaksanaan alternatif bagi thread-safe baris gilir yang menangani isu:
<code class="cpp">template <class T> class SafeQueue { public: SafeQueue() : q(), m(), cv() {} void enqueue(T t) { std::lock_guard<std::mutex> lock(m); q.push(t); cv.notify_one(); } T dequeue() { std::unique_lock<std::mutex> lock(m); while (q.empty()) cv.wait(lock); T val = q.front(); q.pop(); return val; } private: std::queue<T> q; mutable std::mutex m; std::condition_variable cv; };</code>
Dalam pelaksanaan ini, pembolehubah keadaan digunakan dengan betul untuk menunggu keadaan baris gilir kosong (atau tidak kosong untuk kaedah enqueue) menjadi palsu. Benang hanya akan melakukan operasi yang diingini (menyah gilir item) jika baris gilir tidak kosong selepas bangun tidur.
Atas ialah kandungan terperinci Mengapa Saya Mendapat Segfaults Apabila Menggunakan Pembolehubah Keadaan untuk Menyemak Baris Gilir Kosong dalam C?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!