c ++线程,重复/缺失线程

ffo*_*kes 5 c++ lambda multithreading

我正在尝试编写一个程序,同时添加和删除"仓库"中的项目.我有一个"监视"类来处理"仓库"操作:

class Monitor
{
private:
    mutex m;
    condition_variable cv;
    vector<Storage> S;
    int counter = 0;
    bool busy = false;;
public:

    void add(Computer c, int index) {
        unique_lock <mutex> lock(m);
        if (busy)
            cout << "Thread " << index << ": waiting for !busy " << endl;
        cv.wait(lock, [&] { return !busy; });
        busy = true;
        cout << "Thread " << index << ": Request: add " << c.CPUFrequency << endl;

        for (int i = 0; i < counter; i++) {
            if (S[i].f == c.CPUFrequency) {
                S[i].n++;
                busy = false;   cv.notify_one();
                return;
            }
        }
        Storage s;
        s.f = c.CPUFrequency;
        s.n = 1;
        // put the new item in a sorted position
        S.push_back(s);
        counter++;
        busy = false; cv.notify_one();
    }
}
Run Code Online (Sandbox Code Playgroud)

线程是这样创建的:

void doThreadStuff(vector<Computer> P, vector <Storage> R, Monitor &S)
{
    int Pcount = P.size();

    vector<thread> myThreads;
    myThreads.reserve(Pcount);

    for (atomic<size_t> i = 0; i < Pcount; i++)
    {
        int index = i;
        Computer c = P[index];
        myThreads.emplace_back([&] { S.add(c, index); });
    }

    for (size_t i = 0; i < Pcount; i++)
    {
        myThreads[i].join();
    }
// printing results
}
Run Code Online (Sandbox Code Playgroud)

运行该程序产生了以下结果:

在此输入图像描述

我熟悉比赛条件,但对我来说这看起来并不像.我的赌注是与参考相关的东西,因为在结果中我们可以看到,对于每个"缺失的线程"(线程1,3,10,25),我得到"重复的线程"(线程2,9,24,28).

我试图在函数和循环中创建局部变量,但它没有改变任何东西.

我听说线​​程共享内存区域,但我以前的工作应该产生类似的结果,所以我不认为这是这种情况,但随意证明我错了.

我正在使用Visual Studio 2017

lll*_*lll 7

在这里,您通过循环中的引用捕获局部变量,它们将在每个回合中被销毁,从而导致未定义的行为:

for (atomic<size_t> i = 0; i < Pcount; i++)
{
    int index = i;
    Computer c = P[index];
    myThreads.emplace_back([&] { S.add(c, index); });
}
Run Code Online (Sandbox Code Playgroud)

你应该抓住indexc用价值:

myThreads.emplace_back([&S, index, c] { S.add(c, index); });
Run Code Online (Sandbox Code Playgroud)