如何做到线程安全的shared_ptr修改和访问?

问题描述 投票:0回答:1

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

我简化了代码,但这是我试图实现的。

我有2个共享指针。

其中一个叫做 m_mutable_data 而另一个叫 m_const_data.

m_mutable_data 是以字符串保护的方式更新的。m_const_data 每隔60s更新一次m_mutable_data的内容,也是以strand guarded的方式。

这是唯一的地方 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'中的第1行崩溃。

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个回答
1
投票

我想我在这篇文章中找到了问题的答案。原子智能指针.

所以,我必须修改以下代码 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);
© www.soinside.com 2019 - 2024. All rights reserved.