在主题1(释义代码)中:
std::vector<std::shared_ptr<Object>> list;
// Initialization
list.reserve(prop_count);
for (size_t i = 0; i < count; ++i)
{
list.push_back(std::shared_ptr<Object>());
}
// Looped code
for (auto iter = indexes.begin(); iter != indexes.end(); ++iter)
{
uint32_t i = *iter;
std::shared_ptr<Object> item = make_object(table->data[i]); // returns a shared_ptr of Object
list[i].swap(item);
}
线程2中的(释义代码):
for(auto iter = list.begin(); iter != list.end(); ++iter)
{
shared_ptr<Property> o(*iter);
if(o)
{
// some work with casting it
// dynamic_pointer_cast
}
} // <--- crashes here (after o is out of scope)
这是调用堆栈:
0x006ea218 C/C++
std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)1>::_M_release(this = 0x505240) C/C++
std::__shared_count<(__gnu_cxx::_Lock_policy)1>::~__shared_count(this = 0xb637dc94) C/C++
std::__shared_ptr<Property, (__gnu_cxx::_Lock_policy)1>::~__shared_ptr(this = 0xb637dc90) C/C++
std::shared_ptr<Property>::~shared_ptr(this = 0xb637dc90) C/C++
startSending() C/C++
libpthread.so.0!start_thread() C/C++
libc.so.6 + 0xb52b8 C/C++
看看shared_ptr_base.h,它似乎崩溃了:
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
{
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
_M_dispose(); // <--- HERE
我不知道如何解决这个问题。任何帮助表示赞赏。谢谢!
答案 0 :(得分:1)
来自http://en.cppreference.com/w/cpp/memory/shared_ptr,重点强调:
如果多个执行线程访问相同的shared_ptr 没有同步,任何访问都使用非const shared_ptr的成员函数然后将发生数据竞争;该 shared_ptr原子函数的重载可以用来防止 数据竞赛。
在这种情况下,list[i]
和*iter
是相同的实例。
对于主题1,建议使用std::atomic_store(&list[i], item)
代替list[i].swap(item)
对于主题2,建议使用std::shared_ptr<Property> o(std::atomic_load(&*iter))
代替std::shared_ptr<Property> o(*iter);
这一切都假设向量的大小不会改变,并引入容器的线程安全问题,迭代器失效等等。这超出了本问题的范围,但在其他地方也有所涉及。
答案 1 :(得分:0)
1)将数据放到容器上:使用队列,而不是向量。不要保留和交换,只需将它们推入队列即可。 2)每次推送都需要由互斥锁(类成员)保护。
======第二线程=======
3)队列的弹出值,每个弹出都需要由与上面相同的互斥锁保护。
请参阅:Using condition variable in a producer-consumer situation