条件变量基本示例

Its*_*nas 4 c++ condition-variable

我正在学习 C++11 中的条件变量,并根据示例代码编写了这个程序。

目标是将生产者生成并由消费者推入向量的前十个自然整数累积在向量中。然而它不起作用,因为例如在某些运行中,向量仅包含 1、7 和 10。

#include <mutex>
#include <condition_variable>
#include<vector>
#include <iostream>
#include <cstdio>

std::mutex mut;
#define MAX     10
int counter;
bool isIncremented = false;
std::vector<int> vec;
std::condition_variable condvar;

void producer() {
    while (counter < MAX) {
        std::lock_guard<std::mutex> lg(mut);
        ++counter;
        isIncremented = true;
        condvar.notify_one();
    }
}

void consumer() {
    while (true) {
        std::unique_lock<std::mutex> ul(mut);
        condvar.wait(ul, [] { return isIncremented; });
        vec.push_back(counter);
        isIncremented = false;
        if (counter >= MAX) {
            break;
        }
    }
}

int main(int argc, char *argv[]) {
    std::thread t1(consumer);
    std::thread t2(producer);
    t2.join();
    t1.join();

    for (auto i : vec) {
        std::cout << i << ", ";
    }
    std::cout << std::endl;
    // Expected output: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
    // Example of actual output: 1, 7, 10,

    std::cout << "Press enter to quit";
    getchar();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Mic*_*zel 5

问题是你只记得你的制作人生产的最后一个数字。而且你的生产者永远不会等到消费者消费完它生产的东西。如果您的生产者线程在消费者线程开始运行之前执行其循环的多次迭代(这并非不可能,因为循环没有做太多事情),那么消费者将只能看到生产者生成的最后一个数字,并且只能推送那个进入向量\xe2\x80\xa6

\n\n

要解决这个问题,要么使用第二个条件变量让生产者等待某人获取它生成的最后一个结果,要么使用可以在生产者和消费者之间存储多个结果的东西,或者它们的组合\xe2\x80 \xa6

\n\n

注意:通知条件变量不是阻塞调用。如果是的话,它必须要求您交出互斥体,以便它可以在内部释放它,否则您将陷入僵局。notify_one()只会唤醒正在等待条件变量的线程之一并返回。唤醒线程阻塞的等待调用将在返回之前重新获取互斥锁。在您的情况下,消费者线程不太可能被唤醒,然后无法重新获取互斥体并立即再次阻塞,因为您的生产者线程在调用时仍然保留互斥体notify_one()。因此,根据一般经验,如果在调用 notification\xe2\x80\xa6 之前持有与条件变量关联的互斥锁,则需要释放该互斥锁。

\n