- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我读过
"Multiple threads can simultaneously read and write different shared_ptr objects, even when the objects are copies that share ownership." (MSDN: Thread Safety in the Standard C++ Library)
这是否意味着更改 shared_ptr 对象是安全的?
例如,下一个代码是否被认为是安全的:
shared_ptr<myClass> global = make_shared<myClass>();
...
//In thread 1
shared_ptr<myClass> private = global;
...
//In thread 2
global = make_shared<myClass>();
...
在那种情况下,我能否确定线程 1 private
将具有 global
的原始值或线程 2 分配的新值,但无论哪种方式,它都会有一个myClass 的有效 shared_ptr?
==编辑==
只是为了解释我的动机。我想要一个共享指针来保存我的配置,并且我有一个线程池来处理请求。
所以global
是全局配置。线程 1
在开始处理请求时采用当前配置。线程 2
正在更新配置。 (仅适用于 future 的请求)
如果可行,我可以通过这种方式更新配置,而不会在请求处理过程中中断它。
最佳答案
您正在阅读的内容并不代表您认为的意思。首先,尝试 shared_ptr 的 msdn 页面本身。
向下滚动到“备注”部分,您将了解问题的实质。基本上,一个 shared_ptr<>
指向一个“控制 block ”,这是它如何跟踪有多少shared_ptr<>
对象实际上指向“真实”对象。所以当你这样做时:
shared_ptr<int> ptr1 = make_shared<int>();
虽然这里只有 1 次调用通过 make_shared
分配内存,有两个“逻辑” block 你不应该对待相同。一个是 int
其中存储实际值,另一个是控制 block ,存储所有shared_ptr<>
让它发挥作用的“魔法”。
只有控制 block 本身是线程安全的。
为了强调,我把它单独放在一行。 shared_ptr
的内容不是线程安全的,也不是写入相同的 shared_ptr
实例。这里有一些东西可以证明我的意思:
// In main()
shared_ptr<myClass> global_instance = make_shared<myClass>();
// (launch all other threads AFTER global_instance is fully constructed)
//In thread 1
shared_ptr<myClass> local_instance = global_instance;
这很好,事实上您可以在所有线程中尽可能多地执行此操作。然后当local_instance
被破坏(通过超出范围),它也是线程安全的。有人可以访问 global_instance
这不会有什么不同。您从 msdn 中提取的代码段基本上意味着“对控制 block 的访问是线程安全的”,所以其他 shared_ptr<>
可以根据需要在不同的线程上创建和销毁实例。
//In thread 1
local_instance = make_shared<myClass>();
这很好。它将影响global_instance
对象,但只是间接的。它指向的控制 block 将递减,但以线程安全的方式完成。 local_instance
将不再指向与 global_instance
相同的对象(或控制 block )
//In thread 2
global_instance = make_shared<myClass>();
如果global_instance
,这几乎肯定是不好的从任何其他线程访问(你说你正在做)。如果你这样做,它需要一个锁,因为你正在写任何地方 global_instance
生活,而不仅仅是阅读它。所以从多个线程写入一个对象是不好的,除非你通过锁来保护它。所以你可以阅读 global_instance
通过分配新的对象 shared_ptr<>
来自它的对象,但你不能写入它。
// In thread 3
*global_instance = 3;
int a = *global_instance;
// In thread 4
*global_instance = 7;
a
的值未定义。它可能是 7,也可能是 3,也可能是其他任何值。 shared_ptr<>
的线程安全实例仅适用于管理 shared_ptr<>
从彼此初始化的实例,而不是它们指向的实例。
为了强调我的意思,请看这个:
shared_ptr<int> global_instance = make_shared<int>(0);
void thread_fcn();
int main(int argc, char** argv)
{
thread thread1(thread_fcn);
thread thread2(thread_fcn);
...
thread thread10(thread_fcn);
chrono::milliseconds duration(10000);
this_thread::sleep_for(duration);
return;
}
void thread_fcn()
{
// This is thread-safe and will work fine, though it's useless. Many
// short-lived pointers will be created and destroyed.
for(int i = 0; i < 10000; i++)
{
shared_ptr<int> temp = global_instance;
}
// This is not thread-safe. While all the threads are the same, the
// "final" value of this is almost certainly NOT going to be
// number_of_threads*10000 = 100,000. It'll be something else.
for(int i = 0; i < 10000; i++)
{
*global_instance = *global_instance + 1;
}
}
A shared_ptr<>
是一种确保多个对象所有者确保对象被销毁的机制,而不是确保多个线程可以正确访问对象的机制。您仍然需要一个单独的同步机制才能在多个线程中安全地使用它(例如 std::mutex )。
考虑 IMO 的最佳方式是 shared_ptr<>
确保指向同一内存的多个拷贝对自身没有同步问题,但对指向的对象不做任何事情。那样对待它。
关于c++ - std::shared_ptr 线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46547668/
我正在开发一个小型图书馆,我需要做的一件事是让访问者访问一些数据并返回结果。 在一些较旧的 C++ 代码中,访问者需要声明一个 typedef return_type .例如,boost::stati
我正在尝试使用std:map类型的键和值制作std::any Visual Studio 2017 std::map m("lastname", "Ivanov"); std::cout (m["la
我已经在 C++ 的 map 中声明了一个集合为 std::map> .如何循环访问或打印设定值? 最佳答案 如果你知道如何迭代 std::map或 std::set单独地,您应该可以毫无问题地组合迭
如何循环? 我已经试过了: //----- code std::vector >::iterator it; for ( it = users.begin(); it != users.end();
我有两个用例。 A.我想同步访问两个线程的队列。 B.我想同步两个线程对队列的访问并使用条件变量,因为其中一个线程将等待另一个线程将内容存储到队列中。 对于用例 A,我看到了使用 std::lock_
我正在查看这两种类型特征的文档,但不确定有什么区别。我不是语言律师,但据我所知,它们都适用于“memcpy-able”类型。 它们可以互换使用吗? 最佳答案 不,这些术语不能互换使用。这两个术语都表示
我有以下测试代码,其中有一个参数 fS,它是 ofstream 的容器: #include #include #include #include int
这是这个问题的延续 c++ function ptr in unorderer_map, compile time error 我试图使用 std::function 而不是函数指针,并且只有当函数是
std::unordered_map str_bool_map = { {"a", true}, {"b", false}, {"c", true} }; 我们可以在此映射上使
我有以下对象 std::vector> vectorList; 然后我添加到这个使用 std::vector vec_tmp; vec_tmp.push_back(strDRG); vec_tmp.p
为什么 std::initializer_list不支持std::get<> , std::tuple_size和 std::tuple_element ?在constexpr中用得很多现在的表达式,
我有一个像这样定义的变量 auto drum = std::make_tuple ( std::make_tuple ( 0.3f , Ex
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
问题 我正在尝试将 lambda 闭包传递给 std::thread,它使用任意封闭参数调用任意封闭函数。 template std::thread timed_thread(Function&& f
我想创建一个模板类,可以容纳容器和容器的任意组合。例如,std::vector或 std::map ,例如。 我尝试了很多组合,但我必须承认模板的复杂性让我不知所措。我编译的关闭是这样的: templ
我有一个 std::vector>我将其分配给相同类型的第二个 vector 。 我收到这个编译器错误: /opt/gcc-8.2.0/include/c++/8.2.0/bits/stl_algob
有时候,我们有一个工厂可以生成一个 std::unique_ptr vector ,后来我们想在类/线程/你命名的之间共享这些指针。因此,最好改用 std::shared_ptr 。当然有一种方法可以
这个问题在这里已经有了答案: Sorting a vector of custom objects (14 个答案) 关闭 6 年前。 我创建了一个 vector vector ,我想根据我定义的参
我有三个类(class)成员: public: std::vector > getObjects(); std::vector > getObjects() const; privat
我是一名优秀的程序员,十分优秀!