[英]how to reset std::condition_variable
我正在嘗試使用條件變量來觸發第二個線程在一定數量的緩沖區處於雙端隊列之后進行一些工作。
我的問題是在thrd()中,在獲得信號和緩沖區<4之后,它會循環返回while循環並立即再次獲得條件。 有沒有辦法重置簡歷?
deque<int> vbufs;
std::mutex thrdLock;
void thrd()
{
while (true) {
cout << "thrd() waiting for lock\n";
std::unique_lock < std::mutex > lock(thrdLock);
cout << "thrd() waiting for condition\n";
cv.wait(lock, []{ return (vbufs.size() > 0); });
thrdLock.unlock();
cout << "thrd() condition set\n";
if (vbufs.size() >= 4) { // pretend to do something with 4 buffers and remove them
std::lock_guard < std::mutex > lock(thrdLock);
vbufs.pop_front();
vbufs.pop_front();
vbufs.pop_front();
vbufs.pop_front();
cout << "thrd() reducing buffers:" << vbufs.size() << endl;
}
}
}
int main(int argc, char* argv[]) {
std::thread t1(thrd);
int tctr = 0;
while (true) {
usleep(1000);
{
cout << "main() waiting for lock\n";
std::lock_guard < std::mutex > lock(thrdLock);
vbufs.push_back(++tctr);
cout << "main() incremented buffers:" << vbufs.size() << endl;
}
cv.notify_one();
}
return 0;
}
您不能重置條件變量; 這沒有任何意義-通知它不會更改其狀態,因此無需重置。 收到通知后,只能喚醒已經等待的線程。 如果該線程然后再次等待,它將不會繼續,直到重新通知條件變量。
如果您只想在有四個或更多緩沖區的情況下進行工作,是否不應該這樣更改等待時間?
cv.wait(lock, []{ return (vbufs.size() >= 4); });
更重要的是,您可能vbufs
同時從兩個不同的線程讀取和寫入vbufs
您的if (vbufs.size() >= 4)
發生在鎖之外,因此可能與對push_back
的調用同時發生。 這導致不確定的行為,可能會解釋您所看到的。
我在程序中發現了兩個錯誤-此處已糾正:
注意:您直接解鎖互斥鎖而不是通過std::unique_lock
解鎖的方式導致了數據爭用。
#include <iostream>
#include <deque>
#include <mutex>
#include <thread>
#include <chrono>
#include <condition_variable>
std::deque<int> vbufs;
std::mutex thrdLock;
std::condition_variable cv;
template<class...Ts>
void emit(Ts&&...ts)
{
static std::mutex m;
std::lock_guard<std::mutex> lg(m);
using expand = int[];
void(expand { 0, ((std::cout << std::forward<Ts>(ts)), 0)... });
}
void thrd()
{
while (true) {
emit("thrd() waiting for lock\n");
std::unique_lock < std::mutex > lock(thrdLock);
emit("thrd() waiting for condition\n");
cv.wait(lock, []{ return vbufs.size() >= 4; });
emit("thrd() condition set\n");
auto a = vbufs.front(); vbufs.pop_front();
auto b = vbufs.front(); vbufs.pop_front();
auto c = vbufs.front(); vbufs.pop_front();
auto d = vbufs.front(); vbufs.pop_front();
emit("thrd() reducing buffers:", vbufs.size(), '\n');
lock.unlock();
emit(a, ' ', b, ' ', c, ' ', d, '\n');
}
}
int main(int argc, char* argv[]) {
std::thread t1(thrd);
int tctr = 0;
while (true) {
std::this_thread::sleep_for(std::chrono::microseconds(10));
{
emit("main() waiting for lock\n");
std::lock_guard < std::mutex > lock(thrdLock);
vbufs.push_back(++tctr);
emit("main() incremented buffers:", vbufs.size(), '\n');
}
cv.notify_one();
}
t1.join(); // un-necessary in this case, but...
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.