线程之间通过共享向量进行通信

Communication between threads via shared vector

本文关键字:通信 向量 共享 之间 线程      更新时间:2023-10-16

我正在设计一个tcp服务器,它从请求中获取信息,并将所有信息放入队列中进行处理。我正在使用一个asio网络服务器来处理所有的网络交互。我正在寻找一种有效的方法来将所有的东西都排队成为流程。我现在用助推信号和全局矢量来做这件事,类似于这个。

void request_handler::handle_request(request &req, reply &rep)
{
   std::string parsedInfo = parse_request(req); 
   shared_queue.push_back(parsedInfo);
   new_entry();
}

new_entry是一个升压信号

    boost::signal<void ()> new_entry;

现在我有一个信号处理程序类来捕获信号。

void sig_handler::process_next()
{
    boost::try_mutex::scoped_try_lock lock(guard);
    if(!lock)
       return;
    while(!shared_queue.empty())
    {
        ... //Do Stuff
        std::string cur_entry = shared_queue.at(0);
        shared_queue.erase(shared_queue.begin());
        ... //Do more stuff
    } 
}

我的目标是在向量队列中有信息时,以及每次在向量上推送某个东西时,清除该向量队列。我想尽量避免投票。我相信这部分也在按我的预期工作。然而,我偶尔会因为在共享队列上推送信息而崩溃。只有当我尝试每秒处理1000个事务时才会发生这种情况,这使得在多线程环境中调试变得困难。我的回溯在这里:

Error: signal 11:
./UpdateServer/build/UpdateServer(_Z7handleri+0x18)[0x469f68]
/lib/x86_64-linux-gnu/libc.so.6(+0x364a0)[0x7fbbdd67a4a0]
/usr/lib/x86_64-linux-gnu/libstdc++.so.6(_ZNSsC1ERKSs+0xb)[0x7fbbddfb4f2b]
./UpdateServer/build/UpdateServer[0x4749d0]
./UpdateServer/build/UpdateServer(_ZNSt6vectorISsSaISsEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPSsS1_EERKSs+0x111)[0x476521]
./UpdateServer/build/UpdateServer(_ZN15request_handler14handle_requestERK7requestR5reply+0x3d3)[0x475873]
./UpdateServer/build/UpdateServer(_ZN10connection11handle_readERKN5boost6system10error_codeEm+0x234)[0x46c774]
./UpdateServer/build/UpdateServer(_ZN5boost4asio6detail14strand_service8dispatchINS1_7binder2INS_3_bi6bind_tIvNS_4_mfi3mf2Iv10connectionRKNS_6system10error_codeEmEENS5_5list3INS5_5valueINS_10shared_ptrIS9_EEEEPFNS_3argILi1EEEvEPFNSK_ILi2EEEvEEEEESB_mEEEEvRPNS2_11strand_implET_+0xcd)[0x47216d]
./UpdateServer/build/UpdateServer(_ZN5boost4asio6detail15wrapped_handlerINS0_10io_service6strandENS_3_bi6bind_tIvNS_4_mfi3mf2Iv10connectionRKNS_6system10error_codeEmEENS5_5list3INS5_5valueINS_10shared_ptrIS9_EEEEPFNS_3argILi1EEEvEPFNSK_ILi2EEEvEEEEEEclISB_mEEvRKT_RKT0_+0xd9)[0x472439]
./UpdateServer/build/UpdateServer(_ZN5boost4asio6detail18completion_handlerINS1_17rewrapped_handlerINS1_7binder2INS1_15wrapped_handlerINS0_10io_service6strandENS_3_bi6bind_tIvNS_4_mfi3mf2Iv10connectionRKNS_6system10error_codeEmEENS8_5list3INS8_5valueINS_10shared_ptrISC_EEEEPFNS_3argILi1EEEvEPFNSN_ILi2EEEvEEEEEEESE_mEESV_EEE11do_completeEPNS1_15task_io_serviceEPNS1_25task_io_service_operationESG_m+0x1e5)[0x4726f5]
./UpdateServer/build/UpdateServer(_ZN5boost4asio6detail14strand_service8dispatchINS1_17rewrapped_handlerINS1_7binder2INS1_15wrapped_handlerINS0_10io_service6strandENS_3_bi6bind_tIvNS_4_mfi3mf2Iv10connectionRKNS_6system10error_codeEmEENS9_5list3INS9_5valueINS_10shared_ptrISD_EEEEPFNS_3argILi1EEEvEPFNSO_ILi2EEEvEEEEEEESF_mEESW_EEEEvRPNS2_11strand_implET_+0x2ad)[0x472aed]
./UpdateServer/build/UpdateServer(_ZN5boost4asio6detail19asio_handler_invokeINS1_7binder2INS1_15wrapped_handlerINS0_10io_service6strandENS_3_bi6bind_tIvNS_4_mfi3mf2Iv10connectionRKNS_6system10error_codeEmEENS7_5list3INS7_5valueINS_10shared_ptrISB_EEEEPFNS_3argILi1EEEvEPFNSM_ILi2EEEvEEEEEEESD_mEES6_SU_EEvRT_PNS4_IT0_T1_EE+0x15f)[0x472d3f]
./UpdateServer/build/UpdateServer(_ZN5boost4asio6detail23reactive_socket_recv_opINS0_17mutable_buffers_1ENS1_15wrapped_handlerINS0_10io_service6strandENS_3_bi6bind_tIvNS_4_mfi3mf2Iv10connectionRKNS_6system10error_codeEmEENS7_5list3INS7_5valueINS_10shared_ptrISB_EEEEPFNS_3argILi1EEEvEPFNSM_ILi2EEEvEEEEEEEE11do_completeEPNS1_15task_io_serviceEPNS1_25task_io_service_operationESF_m+0xce)[0x472ede]
./UpdateServer/build/UpdateServer(_ZN5boost4asio6detail15task_io_service3runERNS_6system10error_codeE+0x79a)[0x47ceea]
./UpdateServer/build/UpdateServer(_ZN5boost4asio10io_service3runEv+0x25)[0x47d1d5]
/usr/lib/libboost_thread.so.1.48.0(+0xdda9)[0x7fbbdecd4da9]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x7e9a)[0x7fbbdd42ee9a]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x6d)[0x7fbbdd737cbd]

线路./UpdateServer/build/UpdateServer(_ZNSt6vectorISsSaISsEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPSsS1_EERKSs+0x111)[0x476521]

似乎与std::vector insert迭代器相矛盾,这就是为什么我认为我的程序在共享的vector inserter上崩溃的原因(我不相信我的程序中有任何其他字符串的vector),但我相当肯定我在insert和read上都以安全的方式使用了我的vector。

所以我想我的问题是,当我把信息推到一个共享向量上时,是否有我必须担心的种族状况问题会导致我的崩溃?我所采取的方法是可行的,还是应该以某种方式重新思考我的设计?如果你需要更多信息,请告诉我,我很乐意提供任何我能提供的信息。

感谢

std数据结构(在大多数情况下)不是线程安全的,因此如果多个线程同时访问,则需要额外的同步。在您的情况下,一个线程可能正在调用push_back,而另一个线程则在调用erase。这将产生未定义的行为。要解决此问题,push_backerase都需要由同一个锁保护。我建议你在c++标准库中搜索线程安全,并阅读更多关于它的信息。


此外,在这里使用vector可能不是最佳选择。您应该查看std::queue。当您erase时,vector的第一个元素必须稍后在向量向下一个中复制所有字符串,这可能非常昂贵。CCD_ 10不存在该问题。