我正在尝试对原子库进行单元测试(我知道原子库不适合单元测试,但我仍然想尝试一下)

为此,我想让X个并行线程增加一个计数器并评估结果值(应该为X)。

代码如下。问题在于它永远不会中断。 Counter总是以2000结尾(见下文)。我还注意到的是,cout也是作为整体打印的(不是混杂在一起,我记得与其他多线程couts一起看到的内容)

我的问题是:为什么不休息?或者我该如何打破?

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

std::mutex m;
std::condition_variable cv;
bool start = false;

int Counter = 0;

void Inc() {

    // Wait until test says start
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, [] {return start; });

    std::cout << "Incrementing in thread " << std::this_thread::get_id() << std::endl;
    Counter++;
}

int main()
{
    std::vector<std::thread> threads;

    for (int i = 0; i < 2000; ++i) {
        threads.push_back(std::thread(Inc));
    }

    // signal the threads to start
    {
        std::lock_guard<std::mutex> lk(m);
        start = true;
    }
    cv.notify_all();

    for (auto& thread : threads) {
        thread.join();
    }

    // Now check whether value is right
    std::cout << "Counter: " << Counter << std::endl;
}


结果看起来像这样(但是是2000行)

Incrementing in thread 130960
Incrementing in thread 130948
Incrementing in thread 130944
Incrementing in thread 130932
Incrementing in thread 130928
Incrementing in thread 130916
Incrementing in thread 130912
Incrementing in thread 130900
Incrementing in thread 130896
Counter: 2000


任何帮助,将不胜感激

更新:将线程的nr减少到4,但是在for循环中增加了一百万次(如@tkausl所建议),线程ID的cout似乎是顺序的。

UPDATE2:事实证明,必须将锁解锁,以防止每个线程(lk.unlock())的独占访问。 for循环中的其他yield增加了竞争条件的影响。

最佳答案

cv.wait(lk, [] {return start; });仅返回已获取的lk。所以是独家的。您可能想在以下时间立即解锁lk

void Inc() {
    // Wait until test says start
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, [] {return start; });
    lk.unlock();

    Counter++;
}


并且必须删除std::cout,因为它可能会引入同步。

关于c++ - 强制并发修改变量(C++),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53414039/

10-12 00:27