Почему моя многопоточная очередь сбоев? - PullRequest
0 голосов
/ 29 октября 2018

Я пытаюсь запустить многопоточную очередь заданий в 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 голосов
/ 29 октября 2018

Вы обращаетесь к своей очереди без синхронизации:

std::scoped_lock(mtxJobs);

это локальная переменная с именем mtxJobs, которая создается без аргументов и скрывает ваш мьютекс mtxJobs член. Когда scoped_lock создается без аргументов, он ничего не делает в соответствии с reference .

Вам необходимо написать:

std::scoped_lock lock(mtxJobs);

Теперь ваш мьютекс заблокирован в ctor объекта scoped_lock.

...