【问题标题】:How to do thread safe shared_ptr modification and access?如何进行线程安全的 shared_ptr 修改和访问?
【发布时间】:2020-08-30 15:43:46
【问题描述】:

目标:我想修改内部信息,并尽可能快地从多个线程同步访问这些信息

我在下面简化了代码,但这就是我试图实现这一目标的方式。

我有 2 个共享指针。

一个叫做m_mutable_data,另一个叫做m_const_data

m_mutable_data 以链保护方式更新。 m_const_data 每 60 秒更新一次 m_mutable_data 的内容,也是链保护方式。

这是m_const_data 共享指针被新数据重置的唯一地方。 m_const_data被多线程同步读取,每秒1000+次。

代码

class black_list_container : public std::enable_shared_from_this<black_list_container>
{

struct meta_data
{
    bool blacked;
}

struct black_list_data
{
    std::unordered_map<uint32_t,meta_data> data;
}

public:

#pragma optimize( "", off )
bool is_blacked(uint32_t id) 
{
    // This call is called from many different threads (1000+ calls per second)
    // should be synchronous and as fast as possible

    auto c = m_const_data;

    return c->data[id].blacked;
}
#pragma optimize( "", on )

#pragma optimize( "", off )
void update_const_data() 
{
    // Called internaly by timer every 60s to update m_const_data with contents of m_mutable_data
    // Guarded with strand

    m_strand->post([self{shared_from_this()}]{

        auto snapshot = new black_list_data();
        snapshot->data = m_mutable_data->data;
        m_const_data.reset(snapshot);

    });
}
#pragma optimize( "", on )


private:

void internal_modification_mutable_data()
{
    // Called internaly by different metrics
    // Guarded with strand

    m_strand->post([self{shared_from_this()}]{

        // .... do some modification on internal m_mutable_data

    });
}

boost::asio::io_context::strand m_strand;
std::shared_ptr<black_list_data> m_mutable_data;
std::shared_ptr<black_list_data> m_const_data;

};

这个代码很少会在在线方法“is_blacked”中崩溃

auto c = m_const_data;

这是回溯

[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Core was generated by `./STRATUM-01'.
Program terminated with signal 6, Aborted.
#0  0x00007fe09aaf1387 in raise () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-307.el7.1.x86_64 libgcc-4.8.5-39.el7.x86_64 libstdc++-4.8.5-39.el7.x86_64
(gdb) bt
#0  0x00007fe09aaf1387 in raise () from /lib64/libc.so.6
#1  0x00007fe09aaf2a78 in abort () from /lib64/libc.so.6
#2  0x00007fe09ab33ed7 in __libc_message () from /lib64/libc.so.6
#3  0x00007fe09ab3c299 in _int_free () from /lib64/libc.so.6
#4  0x00000000005fae36 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x7fe0440aeaa0) at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/shared_ptr_base.h:154
#5  0x00000000006b9205 in ~__shared_count (this=<synthetic pointer>, __in_chrg=<optimized out>) at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/shared_ptr_base.h:684
#6  ~__shared_ptr (this=<synthetic pointer>, __in_chrg=<optimized out>) at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/shared_ptr_base.h:1123
#7  ~shared_ptr (this=<synthetic pointer>, __in_chrg=<optimized out>) at /opt/rh/devtoolset-7/root/usr/include/c++/7/bits/shared_ptr.h:93
#8  black_list_container_impl::is_blacked (this=0x7fe08c287e50, id=23654) at /var/lib/jenkins/workspace/validator/src/black_list_container.cpp:69

我不确定为什么在第 7 帧中调用 shared_ptr 的销毁

显然我没有实现我的目标,所以请引导我进入真正以线程安全方式实现我的目标的模式。

我知道我可以使用

std::atomic<std::shared_ptr<black_list_data>> m_const_data;

但这不会影响从许多不同线程读取时的性能吗?

【问题讨论】:

    标签: c++ multithreading thread-safety boost-asio


    【解决方案1】:

    我想我在这篇文章Atomic Smart Pointers 中找到了我的问题的答案。

    所以我必须将update_const_data() 中的代码更改为

        auto snapshot = std::make_shared<black_list_data>();
        snapshot->data = m_mutable_data->data;
        std::atomic_store(&m_const_data, snapshot);
    

    is_blacked()中的代码到

    auto c = std::atomic_load(&m_const_data);
    

    【讨论】:

    猜你喜欢
    • 2019-11-23
    • 1970-01-01
    • 2021-12-19
    • 2013-01-07
    • 2019-06-07
    • 2016-09-05
    • 1970-01-01
    相关资源
    最近更新 更多