如何重置std :: condition_variable

use*_*431 1 c++ multithreading thread-safety

我试图使用条件变量触发第二个线程在一定数量的缓冲区处于双端队列中后做一些工作.

  • main()在紧密且时间敏感的循环中读取ADC数据
  • main()将缓冲区添加到双端队列(由线程池管理器处理)
  • deque深度是可变的,所以在main()中测试深度> = 4,然后调用notify_one是不可能的(即:在重处理时间,双端队列的深度可能高达200或300缓冲区或少至光处理时4)
  • thrd()永远不需要发信号main()

我的问题是在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;
}
Run Code Online (Sandbox Code Playgroud)

Ala*_*kes 6

您无法重置条件变量; 这没有任何意义 - 通知它不会改变它的状态,所以没有什么可以重置.当通知它时,只有已经等待的线程才能被唤醒.如果该线程再次等待,则在重新通知条件变量之前它不会继续.

如果你只想在有四个或更多缓冲区的情况下工作,你不应该改变你的等待吗?

cv.wait(lock, []{ return (vbufs.size() >= 4); });
Run Code Online (Sandbox Code Playgroud)

更重要的是,你可能vbufs同时从两个不同的线程读取和写入 - 你if (vbufs.size() >= 4)发生在锁定之外,因此可以在调用的同时发生push_back.这会导致未定义的行为,这可能会解释您所看到的内容.