为什么我的多线程作业队列崩溃了?

时间:2018-10-29 16:05:22

标签: c++ multithreading queue mutex

我正在尝试在c ++中运行多线程作业队列。例如,我已经测试了以下程序:

#include <thread>
#include <mutex>
#include <list>
#include <vector>


class Job
{
    public:
        void Run(void)
        {
        }
};


class Queue
{
    private:
        std::recursive_mutex mtxJobs;
        std::list<Job *> mJobs;
    public:
        Job *Take(void)
        {
            std::scoped_lock(mtxJobs);
            if (mJobs.size() > 0)
            {
                Job *pJob(mJobs.front());
                mJobs.pop_front();
                return pJob;
            }
            else
                return NULL;
        }

        void Add(Job *pJob)
        {
            std::scoped_lock(mtxJobs);
            mJobs.push_back(pJob);
        }

        size_t Size(void)
        {
            std::scoped_lock(mtxJobs);
            return mJobs.size();
        }
};


void Work(Queue &q)
{
    Job *pJob;
    while ((pJob = q.Take()) != NULL)
    {
        pJob->Run();

        delete pJob;
    }
}

int main()
{
    size_t i;
    Queue q;

    for (i = 0; i < 1000; i++)
        q.Add(new Job);

    std::vector<std::thread> threads(4);
    for (i = 0; i < 4; i++)
        threads[i] = std::thread(Work, std::ref(q));

    for (i = 0; i < 4; i++)
        threads[i].join();

    return 0;
}

当我这样运行时:

g++ -std=c++17 -lpthread test.cpp -o test && ./test

使用SEGFAULT崩溃。有谁知道为什么吗?

GDB指示当访问列表'mJobs'时总是发生崩溃。但是,锁应该阻止并发修改吗?

有人可以帮助我吗?

1 个答案:

答案 0 :(得分:3)

您正在访问队列而不同步:

std::scoped_lock(mtxJobs);

这是名称为mtxJobs的局部变量,它是不带任何参数创建的,并且隐藏了互斥体mtxJobs成员。创建scoped_lock不带参数时,根据reference,它不执行任何操作。

您需要写:

std::scoped_lock lock(mtxJobs);

现在,您的互斥锁已锁定在scoped_lock对象的ctor中。