阅读笔记-线程安全的对象生命周期管理

  • 避免使用原始指针,最佳实践是shared_ptr和weak_ptr的结合。因为原始指针容易造成空悬指针/野指针(因为在一个线程里调用一个对象,这个对象可能在其他的线程里被销毁了), shared_ptr通过引用计数的方式保证有线程引用对象的时候,对象不会被销毁,weak_ptr的引入可以避免shared_ptr带来的延长对象生命周期的问题。

  • 用enable_shared_ptr可以避免回调函数注册时传入的对象指针this,在回调的时候变成野指针(boost::bind传入this作为当前对象,但是在回调的时候,this可能被销毁了)

  • 前台线程读(多个,高并发), 后台线程写(少量,低频)

可以用互斥锁来解决这个问题, shared_ptr存放Map,shared_ptr.swap()实现copy on write

class CustomerData : boost::noncopyable
{
public:
    CustomerData() : _data(new Map) {
    }
    int query(const string& customer, const string& stock) const {
        MapPtr data = getData();

        Map::const_iterator entries = data->find(customer);
        if (entries != data->end()) {
            return findEntry(entries->second, stock);
        } else {
            return -1;
        }
    }

    void update(const string& customer, const EntryList& entries) {
        MutexLockGuard lock(_mutex);
        if (!_data.unique()) {
            MapPtr newData(new Map(*_data));
            _data.swap(newData);
        }
        assert(_data.unique());
        (*_data)[customer] = entries;
    }

    static int findEntry(const EntryList& entries, const string& stock);

    MapPtr getData() const {
        MutexLockGuard(_mutex);
        return _data;
    }

private:
    typedef std::pair<string, int> Entry;
    typedef std::vector<Entry> EntryList;
    typedef std::map<string, EntryList> Map;
    typedef boost::shared_ptr<Map> MapPtr;

    mutable MutexLock _mutex;
    MapPtr _data;
};

参考

  1. 《Linux多线程服务端变成》 陈硕