C++ 共享指针的线程安全性&x27;控制块

C++ 共享指针的线程安全性&x27;控制块,c++,multithreading,smart-pointers,C++,Multithreading,Smart Pointers,我正在开发一个利用共享指针的小程序。我有一个简单的类“Thing”,它只是一个具有整数属性的类: class Thing{ public: Thing(int m){x=m;} int operator()(){ return x; } void set_val(int v){ x=v; } int x; ~Thing(){ std::cout<<"Deleted th

我正在开发一个利用共享指针的小程序。我有一个简单的类“Thing”,它只是一个具有整数属性的类:


class Thing{
public:
    Thing(int m){x=m;}
    int operator()(){
        return x;
    }
    void set_val(int v){
        x=v;
    }
    int x;
    ~Thing(){
        std::cout<<"Deleted thing with value "<<x<<std::endl;
    }

};
我在这里的想法是,由于每个共享指针控制块成员函数都是线程安全的,因此在fun()函数中使用_count()的调用不是原子指令,因此不需要锁定。然而,无论是在没有锁紧装置的情况下还是在没有锁紧装置的情况下,这仍然会导致比赛状态。我希望看到的结果是:

1:2 2:3 3:4


由于每个线程生成对原始共享指针的新引用,因此use_count()每次将增加1个引用。但是,由于某些竞争条件,我的输出仍然是随机的。

在多线程环境中,
use\u count()
是近似值。发件人:

在多线程环境中,use\u count返回的值是近似值(典型实现使用内存\u顺序\u松弛加载)

shared\u ptr
的控制块是线程安全的:

所有成员函数(包括复制构造函数和复制分配)都可以由共享\u ptr的不同实例上的多个线程调用,而无需额外同步,即使这些实例是同一对象的副本并共享其所有权

看到过期的
use\u count()
并不表示控制块已被争用条件损坏


请注意,这并不扩展到修改指向的对象。它不提供指向对象的同步。只有
共享\u ptr
和控制块的状态受保护。

在多线程环境中,
使用\u count()
是近似值。发件人:

在多线程环境中,use\u count返回的值是近似值(典型实现使用内存\u顺序\u松弛加载)

shared\u ptr
的控制块是线程安全的:

所有成员函数(包括复制构造函数和复制分配)都可以由共享\u ptr的不同实例上的多个线程调用,而无需额外同步,即使这些实例是同一对象的副本并共享其所有权

看到过期的
use\u count()
并不表示控制块已被争用条件损坏


请注意,这并不扩展到修改指向的对象。它不提供指向对象的同步。只有
共享的\u ptr
和控制块的状态受到保护。

>在fun()函数中使用\u count()的调用不是一条原子指令,因此不需要锁定。我认为您对什么是原子以及什么需要锁定有点困惑。您能稍微扩展一下吗?我仍然习惯于何时使用锁定以及什么是原子指令。原子指令是那些与
std::atomic
绑定的指令。如果从两个线程同时访问非原子对象,则需要一个锁(除非另有指定,例如
std::mutex::lock
)。在您的示例中,您可以从3个不同的线程访问3个不同的
shared_ptr
对象。此外,
shared\u ptr::use\u count
是常量。所以不需要锁。注释部分的扩展有点困难,但请参见示例:>在fun()函数中使用_count()的调用不是原子指令,因此不需要锁定。我认为您对什么是原子以及什么需要锁定有点困惑。您能稍微扩展一下吗?我仍然习惯于何时使用锁定以及什么是原子指令。原子指令是那些与
std::atomic
绑定的指令。如果从两个线程同时访问非原子对象,则需要一个锁(除非另有指定,例如
std::mutex::lock
)。在您的示例中,您可以从3个不同的线程访问3个不同的
shared_ptr
对象。此外,
shared\u ptr::use\u count
是常量。所以不需要锁。在注释部分有点难以展开,但请参见示例:我知道共享_ptr中的对象本身不是线程安全的,但是在这种情况下,您所说的近似值是什么意思?这是否意味着没有真正的方法来同步此操作?@ElliottGoldstein这意味着在多线程上下文中没有有用的方法使用
use\u count()
。@ElliottGoldstein在您读取计数器时,它可能已经更改了。请注意,在您的测试中,存储在
std::thread
中的
shared_ptr
的实例可能更多,并且在下一个线程开始之前,您的一些、全部或全部测试用例可能已经完成,这意味着同时发生的实例可能比您预期的要少。我明白了,谢谢!!我知道shared_ptr中的对象本身不是线程安全的,但是在这种情况下,您所说的近似值是什么意思?这是否意味着没有真正的方法来同步此操作?@ElliottGoldstein这意味着在多线程上下文中没有有用的方法使用
use\u count()
。@ElliottGoldstein在您读取计数器时,它可能已经更改了。请注意,在您的测试中,存储在
std::thread
中的
shared_ptr
的实例可能更多,并且在下一个线程开始之前,您的一些、全部或全部测试用例可能已经完成,这意味着同时发生的实例可能比您预期的要少。我明白了,谢谢!!
std::mutex mtx1;
void fun(std::shared_ptr<Thing> t1,int index){
    std::lock_guard <std::mutex> loc(mtx1);
    int m=t1.use_count();
    std::cout<<index<<" : "<<m<<std::endl;
}

    std::shared_ptr<Thing> ptr5(nullptr);
    ptr5=std::make_shared<Thing>(110);
    std::thread t1(fun,ptr5,1),t2(fun,ptr5,2),t3(fun,ptr5,3);
    t1.join();
    t2.join();
    t3.join();