C++11中智能指针:shared_ptr的引用计数是线程安全的吗?
先说结论,shared_ptr的引用计数是线程安全的,但shared_ptr管理的对象本身不是线程安全的。
一、为什么引用计数是线程安全的?
shared_ptr内部有一个控制块(control block)
多个shared_ptr指向同一个对象时:
std::shared_ptr<int> p1(new int(10)); std::shared_ptr<int> p2=p1; 此时:控制块内的ref_conut=2如果多个线程同时拷贝/销毁shared_ptr,为了避免竞态条件,标准库中使用原子操作(std::atomic<long>),所以引用计数的增加和减少是线程安全的。
二、为什么对象本身不是线程安全的?
假设:
std::shared_ptr<int> p(new int(0)); (*p)++; //两个线程都进行此操作两个线程同时修改同一个对象,shared_ptr并没有加锁,会产生数据竞争吧,因此对象访问需要自己加锁。
例如:
//线程函数内加锁后再访问对象 std::mutex mx; std::lock_guard<std::mutex> lock(mx); (*p)++;三、还有一个最大的误区
很多人学的比较浅的时候会误认为shared_ptr本身完全线程安全,其实线程安全的是多个shared_ptr指向同一个对象,因为有原子操作嘛
例如:
std::shared_ptr<int> p = make_shared<int>(10); thread1: auto p1=p; thread2: auto p2=p;但如果是多个线程同时修改一个shared_ptr对象时,就需要同步机制啦
