加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c 11 – 使用std :: unique_ptr / std :: shared_ptr确认线程安

发布时间:2020-12-16 10:33:26 所属栏目:百科 来源:网络整理
导读:我的应用程序有一个基本上是普通客户端的IRC模块.由于这是严格的线程,我冒着插件检索的风险,例如,用户昵称 – 它当时有效,但解析器触发更新,更改所述昵称. 一旦另一个线程再次执行,它就会处理一个指向现在无效内存的指针,因为它不可能将返回副本作为原子操作
我的应用程序有一个基本上是普通客户端的IRC模块.由于这是严格的线程,我冒着插件检索的风险,例如,用户昵称 – 它当时有效,但解析器触发更新,更改所述昵称.
一旦另一个线程再次执行,它就会处理一个指向现在无效内存的指针,因为它不可能将返回副本作为原子操作.

基于以下代码,我的假设是正确的吗?因此,我想我必须使用通常的互斥锁定/解锁方法,除非有人可以确认或建议否则(我宁愿不必转换并返回shared_ptr,但我想这是一个有效的选项,它是只是我打算SWIG这个,不知道它是否不喜欢它们.

IrcUser.h

class IrcUser : public IrcSubject
{
private:
    ...
    std::shared_ptr<std::string>    _nickname;
    std::shared_ptr<std::string>    _ident;
    std::shared_ptr<std::string>    _hostmask;
public:
    ...
    const c8*
    Ident() const
    { return _ident.get()->c_str(); }

    const c8*
    Hostmask() const
    { return _hostmask.get()->c_str(); }

    const u16
    Modes() const
    { return _modes; }

    const c8*
    Nickname() const
    { return _nickname.get()->c_str(); }

    bool
    Update(
        const c8 *new_nickname,const c8 *new_ident,const c8 *new_hostmask,const mode_update *new_modes
    );
};

IrcUser.cc

bool
IrcUser::Update(
    const c8 *new_nickname,const mode_update *new_modes
)
{
    if ( new_nickname != nullptr )
    {
        if ( _nickname == nullptr )
        {
            *_nickname = std::string(new_nickname);
        }
        else
        {
            _nickname.reset();
            *_nickname = std::string(new_nickname);
        }

        Notify(SN_NicknameChange,new_nickname);
    }

    ...
}

解决方法

代码具有竞争条件,因此具有未定义的行为,因为在同一对象上存在可能的读取( – > get())和写入(.reset()或=)(std :: shared_ptr< std来自不同线程的:: string> instance):必须同步对std :: shared_ptrs的访问.

注意在getter中锁定std::mutex并返回c_str()是不够的,因为getter的调用者将在锁之外使用c_str()的结果:getter需要按值返回shared_ptr.

纠正:

>将一个std :: mutex添加到IrcUser(请注意,这使得该类不可复制):

mutable std::mutex mtx_; // Must be mutable for use within 'const'

>在getter和Update()中锁定std :: mutex,使用std::lock_guard进行异常安全:

std::shared_ptr<std::string> Nickname() const
{
    std::lock_guard<std::mutex> l(mtx_);
    return _nickname;
}

bool IrcUser::Update(const c8 *new_nickname,const mode_update *new_modes)
{
    if (new_nickname)
    {
        {
            std::lock_guard<std::mutex> l(mtx_);
            _nickname.reset(new std::string(new_nickname));
        }
        // No reason to hold the lock here.
        Notify(SN_NicknameChange,new_nickname);
    }

    return true;
}

如果复制是可接受的,请考虑使用std :: string,因为shared_ptr可能会增加不必要的复杂性.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读