【问题标题】:Why does my multithreaded job queue crash?为什么我的多线程作业队列会崩溃?
【发布时间】:2018-10-29 16:05:22
【问题描述】:

我正在尝试在 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”时总是发生崩溃。但是,锁应该防止并发修改吧?

谁能帮帮我?

【问题讨论】:

  • 注意+ 考虑绕过a std::unique_ptr&lt;Job&gt;,而不是newing 和deleteing Jobs。它明确声明了Job 的所有权,并且几乎可以保证如果在此过程中出现任何问题,它就会被释放。

标签: c++ multithreading queue mutex


【解决方案1】:

您正在访问您的队列而没有同步:

std::scoped_lock(mtxJobs);

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

你需要写:

std::scoped_lock lock(mtxJobs);

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

【讨论】:

  • 是的。这就是为什么最好改用lock_guard
  • 我怎么会错过!我按照你说的改了,现在我再也没有崩溃了。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-18
  • 2017-03-26
  • 1970-01-01
相关资源
最近更新 更多