C++ 同步对象是保持线程安全的好方法吗?

C++ 同步对象是保持线程安全的好方法吗?,c++,multithreading,locking,shared-ptr,atomic,C++,Multithreading,Locking,Shared Ptr,Atomic,根据,我们知道shared_ptr::reset()是线程安全的。 防止其他线程访问的对象被释放。我创建了一个storeptr来保存过期的对象。 那么,以下代码在任何时候都是线程安全的 类数据\u信息 { 共享ptr使用; 共享存储; } //函数1和函数2在不同的线程中使用; 无效功能1(数据信息与分析) { a、 使用->做某事(); } 无效功能2(数据信息与分析) { a、 存储=a.使用; a、 使用.reset(新示例()); } 我写了一个演示来证实我的想法 #包括 #包括 #包

根据,我们知道
shared_ptr::reset()
是线程安全的。 防止其他线程访问的对象被释放。我创建了一个
store
ptr来保存过期的对象。 那么,以下代码在任何时候都是线程安全的

类数据\u信息
{
共享ptr使用;
共享存储;
}
//函数1和函数2在不同的线程中使用;
无效功能1(数据信息与分析)
{
a、 使用->做某事();
}
无效功能2(数据信息与分析)
{
a、 存储=a.使用;
a、 使用.reset(新示例());
}
我写了一个演示来证实我的想法

#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
#定义原子读取锁(存储的数据)\
{                                    \
自动原子读取锁定名称=存储的数据ptr;
#定义原子_READLOCK_RELEASE()\
}
#定义原子写入锁(存储数据ptr、新数据ptr)\
存储的\u数据\u ptr=新的\u数据\u ptr
分类栏
{
公众:
bar():num(1){}
显式条(intx):num(x){}
int get_num()
{
返回num;
}
无效集合数量(整数x)
{
num=x;
}
私人:
int-num;
};
向量v;
共享ptr ptr_1、ptr_2;
void get_func()
{
对于(int i=0;i<100000;i++)
{
原子读锁(ptr_1);
v、 向后推(ptr_1->get_num());
原子读取锁定释放();
}
}
无效集_func()
{
对于(int i=0;i<100000;i++)
{
ptr_2=使_共享(i);
原子写锁(ptr_1,ptr_2);
}
}
int main()
{
std::线程t1(get_func);
std::线程t2(set_func);
t1.join();
t2.连接();
}
但它发生在堆芯转储中

[启用使用libthread\u db的线程调试]
使用主机libthread_db library“/lib/x86_64-linux-gnu/libthread_db.so.1”。
核心是由“./reset”生成的。
程序以信号SIGSEGV终止,分段故障。
#标准中的0 0x000055A2A075C58::_Sp_counted_base::_M_release()()
[当前线程为1(线程0x7f70244ec700(LWP 30265))]
(gdb)在哪里
#标准中的0 0x000055A2A075C58::_Sp_counted_base::_M_release()()
#标准中的1 0x000055A2A0758B9:\uuuu共享计数::~\uuu共享计数()
#标准中的2 0x000055A2A075790::\uuuu共享\u ptr::~\uuuu共享\u ptr()()
#std::shared_ptr::~shared_ptr()中的3 0x000055A2A0757C2()
#get_func()中的4 0x000055A2A0753C()
#5 0x000055A2A076069无效标准::uu invoke_impl(标准::uu invoke_other,void(*&)()
#标准中的6 0x000055A2A075B3E::uu invoke_result::键入标准::u invoke(void(*&&)()()
#7 0x000055A2A077B52在decltype中(u invoke((_S_declval)())std::thread::_Invoker::_M_invoke(std:_Index_tuple)()
#std::thread::_Invoker::operator()()()中的8 0x000055A2A077AF0
#std::thread::_State_impl::_M_run()()中的9 0x000055A2A077A3C
#10 0x00007F7051706DF英寸??()来自/usr/lib/x86_64-linux-gnu/libstdc++.so.6
#在pthread_create的start_线程(arg=0x7f70244ec700)中有11个0x00007f7024c836db。c:463
#位于../sysdeps/unix/sysv/linux/x86_64/clone.S:95的clone()中的12 0x00007f70249aca3f

我认为您的代码是线程安全的。但我还建议另一种解决方案,在该方案中,访问类成员的线程将获得
shared\u ptr
的所有权。它本质上使整个场景线程安全

void函数1(数据信息与分析){
自动成员=a.成员;
成员->做某事();
}
无效功能2(数据信息与分析){
a、 member=std::make_shared();
}

但您将如何删除保留
共享\u ptr
。当在某个地方调用
.dosmth()
时,reserve可能会超出范围。
要做到这一点,您需要
弱\u ptr

upd: 是的,看起来很安全

upd2: 所以我们这里有:
对于
弱\u ptr
.lock()
共享\u ptr
的ref计数器,当
锁()
填充未完成时,增益+1(参见链接)。
对于
->
共享\u ptr
它没有。我刚才已经测试过了

因此它不是线程安全的,也不会工作。

要查看它的
dosmth()
运行时间应该比所有其他的运行时间都长,并且在代码中使用

,如果function1(thread1)是
执行某些操作时,function2(t2)释放此对象function1正在使用的是什么now@Smilencer 1. <
function1
中的code>auto member
拥有所有权。2. <代码>功能2
释放所有权。但是由于
function1
持有
auto-member
auto-member
持有引用计数,因此下面的对象不会被释放。但是在这种情况下,您将使用
auto-member
执行smth,与
a.member
@Ааааачааааааачааааааа。是的,会有用的