c ++ 11 shared_ptr在多线程中使用

时间:2016-11-03 03:13:16

标签: c++ multithreading c++11

最近我在想一个使用c ++ 11的高性能事件驱动的多线程框架。它主要考虑了{+ 1}},std::threadstd::condition_variablestd::mutex等c ++ 11设施。一般来说,这个框架有三个基本组成部分:工作,工人和流线,好吧,它似乎是一个真正的工厂。当用户在服务器端构建他的业务模型时,他只需要考虑数据及其处理器。一旦建立了模型,用户只需要构造数据类继承的作业和处理器类继承的worker。

例如:

std::shared_ptr

当服务器获取数据时,它只是通过数据源回调线程中的class Data : public job {}; class Processsor : public worker {}; 新建一个Data对象并调用streamline。 auto data = std::make_shared<Data>()将处理器和数据传输到其他线程。当然,用户不必考虑释放内存。精简。 job_dispatch主要做以下事情:

job_dispatch

void evd_thread_pool::job_dispatch(std::shared_ptr<evd_thread_job> job) { auto task = std::make_shared<evd_task_wrap>(job); task->worker = streamline.worker; // worker has been registered in streamline first of all { std::unique_lock<std::mutex> lck(streamline.mutex); streamline.task_list.push_back(std::move(task)); } streamline.cv.notify_all(); } 中使用的evd_task_wrap定义为:

job_dispatch

最后,task_wrap将通过struct evd_task_wrap { std::shared_ptr<evd_thread_job> order; std::shared_ptr<evd_thread_processor> worker; evd_task_wrap(std::shared_ptr<evd_thread_job>& o) :order(o) {} }; 对象task_list分派到处理线程中。并且处理线程主要执行以下操作:

std::list

但我不知道为什么这个过程经常会在void evd_factory_impl::thread_proc() { std::shared_ptr<evd_task_wrap> wrap = nullptr; while (true) { { std::unique_lock<std::mutex> lck(streamline.mutex); if (streamline.task_list.empty()) streamline.cv.wait(lck, [&]()->bool{return !streamline.task_list.empty();}); wrap = std::move(streamline.task_list.front()); streamline.task_list.pop_front(); } if (-1 == wrap->order->get_type()) break; wrap->worker->process_task(wrap->order); wrap.reset(); } } 函数中崩溃。并且coredump提示有时包裹是一个空的shared_ptr或段错误发生在thread_proc中,在wrap.reset()中调用。我认为shared_ptr在这种情况下有线程同步问题,而我知道shared_ptr中的控制块是线程安全的。当然,_Sp_counted_ptr_inplace::_M_disposejob_dispatch中的shared_ptr是不同的shared_ptr对象,即使它们指向相同的存储。有没有人对如何解决这个问题有更具体的建议?或者,如果存在类似的轻量级框架,使用c ++ 11进行自动内存管理

process_task的例子如: thread_proc

1 个答案:

答案 0 :(得分:-1)

我在您的代码中发现了一个问题,该问题可能与否有关:

您使用条件变量中的notify_all。这将唤醒所有线程从睡眠状态。如果你将wait包裹在while循环中就可以了,例如:

while (streamline.task_list.empty())
    streamline.cv.wait(lck, [&]()->bool{return !streamline.task_list.empty();});

但由于您使用的是if,所有主题都会离开wait。如果您调度单个产品并具有多个消费者线程,则除了一个线程之外的所有线程都会在任务列表为空时调用wrap = std::move(streamline.task_list.front());并导致UB。