智能指针一定智能吗?

智能指针一定智能吗?答案是否定的。要看场景。智能指针随意释放所照成的内存被回收可能会存在很多问题。 讲一个场景,有一个服务需要从磁盘上加载数据到hash表,这个hash表的数据比较大,大约占30G内存。机器的内存目前不太够,只预留了大约服务所占最大内存的2倍。同时,该函数会每小时reload一次。但是可能会在多线程里面并发调用。

目前代码如下:

//其它线程会通过调用get函数来获取这个数据管理对象
std::shared_ptr<DataManager> get(){
    std::lock_guard<std::mutex> g(_mu);
    return _obj;
}
//reload线程会通过这个函数来重新加载新的数据
int reload(const std::string& file) {
        _mu.lock();
        if (status == true) {
            _mu.unlock();
            return -2;
        }
        status = true;
        _mu.unlock();
        auto o = std::make_shared<DataManager>(Config::instance().server.data_count);
        if (0 != o->load(file)) {
            _mu.lock();
            status = false;
            _mu.unlock();
            return -1;
        }
        _mu.lock();
        _obj = o;
        status = false;
        _mu.unlock();
        return 0;
    }

上面代码有啥问题呢?

平时我们在使用智能指针的,很少自己去释放智能指针所持有的对象。总是靠智能指针自己去释放。我们都知道,智能指针的生命周期是当智能指针的引用计数减为0时,所持有的对象也需要被释放。

那么,上面的函数的并发的时候,可能会有个大坑。_obj = o 这一行,因为此时_obj所持有的对象在这里可能无人持有了,要释放了,如果数据量比较大,释放的时间会比较慢,导致持有_mu的锁时间会比较长。

修改之后的代码如下:

int reload(const std::string& file) {
        _mu.lock();

        if (status == true) {
            _mu.unlock();
            return -2;
        }
        status = true;
        _mu.unlock();
        auto o = std::make_shared<DataManager>(Config::instance().server.data_count);
        if (0 != o->load(file)) {
            o = nullptr; 
            _mu.lock();
            status = false;
            _mu.unlock();
            return -1;
        }
        _mu.lock();
        std::shared_ptr<DataManager> tmp = _obj; //此行代码是关键。
        _obj = o;
        status = false;
        _mu.unlock();
        return 0;
    }

所以,在使用智能指针的时候,一定要记得,它是在啥时候被释放掉的。

转载于:https://my.oschina.net/xloogson/blog/799440

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值