c++ string线程安全吗
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++ string线程安全吗相关的知识,希望对你有一定的参考价值。
c++ string线程安全的总结如下:C++11标准之前,C++标准中根本没有线程的概念,所以无从谈起线程
安全,特定实现的线程安全性不能适用于所有别的实现。C++11中标准也只能保证
并发的读操作是线程安全的。
特定的实现可能可以保证某些类的并发写入是线程安全的,比如微软的库:c9ceah3b。
但是GCC 的库则基本上只能保证开发者在正确用锁互斥的时候是线程安全的:
void thread_main ()
library_class_b *object_b = new library_class_b;
shared_object_a.add_b (object_b); // 在对象 shared_object_a上持有锁
shared_object_a.mutate (); // shared_object_a
参考技术A 所有的C++11之前的std库都不是线程安全的。需要自己加锁。至于C++11以后的,我就不太清楚了。本回答被提问者采纳
c++ 当在一个线程中写入并在第二个线程中读取同一个对象时会发生啥? (它安全吗?)[重复]
【中文标题】c++ 当在一个线程中写入并在第二个线程中读取同一个对象时会发生啥? (它安全吗?)[重复]【英文标题】:c++ what happens when in one thread write and in second read the same object? (is it safe?) [duplicate]c++ 当在一个线程中写入并在第二个线程中读取同一个对象时会发生什么? (它安全吗?)[重复] 【发布时间】:2018-06-12 09:17:27 【问题描述】:当在一个线程中写入和在第二个线程中读取同一个对象时会发生什么?会导致应用崩溃?
我的想法是,在主线程上将数据保存到对象或从对象更改数据,而在第二个线程上只读取这些数据。
如果我理解,问题可能只是在写入对象新值并同时从同一个对象读取时,读取值将是旧的。但这对我来说不是问题。
我搜索了我的问题并找到了这个主题What happens if two threads read & write the same piece of memory,但我不确定它是否适用于我的问题。
【问题讨论】:
【参考方案1】:除非对象是原子的,否则一个线程写入和另一个线程读取同一对象的行为是未定义。
您目前认为唯一的问题是可以读取状态数据的看法是不正确的。您不能假设这只是未定义行为的表现。特别是,您很可能会发现您读取的值既不是旧值也不是新值。
【讨论】:
可能值得一提的是,一个特别合理的失败是读取的值既不是旧值也不是新值。但是,根据优化器的不同,代码绝对可以做任何事情。 @MartinBonner 已添加。 @Bathsheba 理解你,如果对象是原子的,那么它会好吗?例如,'std::atomic<:tm> time_object;'在不同线程中同时读取和写入该对象不会导致未定义的行为?我问是因为你的“除非对象是原子的”,可以用我的语言翻译(意思)“如果对象是原子的,行为是未定义的”或“如果对象不是原子的,行为是未定义的”。【参考方案2】:这实际上取决于您尝试读取和写入的内存块的大小。如果您正在读取单个原子数据类型,那么您只能读取和写入整个内存块(以 int 为例)。您可以不确定地从数据类型中获取新值或旧值,而不会出现任何问题。
如果您正在读取和写入非原子内存块,那么在读取周期中,某些块可能会被覆盖,因此信息可能会被破坏。这会导致一些疯狂的行为,并可能导致中断。
https://en.wikipedia.org/wiki/Linearizability
【讨论】:
int
是原子的隐藏假设非常顽皮。
是的,我觉得不好说但是google.co.uk/…
您也忘记了缓存一致性问题。例如,在 ARM 上,一个内核可以在循环中写入一个值,而另一个内核可以读取一个值并等待它在循环中更改并且永远不会看到更改。写入始终进入 L1 缓存,并且永远不会被其他核心缓存刷新和看到。【参考方案3】:
这不安全。考虑使用互斥锁来避免内存损坏:
http://en.cppreference.com/w/cpp/thread/mutex
【讨论】:
【参考方案4】:通常结果是未定义的。你必须做一些事情来定义它,并且你有很多文档要阅读。
编译器必须知道它下面的值可能会被更改。否则优化器会做错事,写操作会被完全忽略。这里的关键字是volatile
。当变量从信号处理程序或硬件本身更改时,这是必需的。不足以支持多线程。
您必须确保读取和写入不会中断。一种方法是使用原子类型。另一种是使用锁或互斥锁来保护对变量的访问。原子类型的大小受硬件支持的限制,因此除了简单的整数或单指针之外的任何东西都需要锁。 std::atomic 类型将其抽象出来。它知道哪些类型在您的硬件上是原子的,以及何时需要使用锁定。
即使这样还不够,因为读取和写入的时间仍然是随机的。如果一个线程写入而另一个线程读取它将读取什么?第二个线程会在第一次写入之前还是之后读取?即使正确使用原子或锁,您也不知道天气,您将获得旧值或新值。如果这很重要,您必须在线程之间进行同步,以便定义读取和写入的顺序。寻找条件。
【讨论】:
volatile
在 C++ 中非常有用,如果您处理的内存映射硬件可能会因为发生的事情而发生变化。在处理多线程 C++ 时几乎没有使用。 std::atomic
也适用于任何可简单复制的类型(尽管如果类型太大,它内部会有一个互斥锁)。
volatile
不用于多线程 Volatile and multithreading: Is the following thread-safe?以上是关于c++ string线程安全吗的主要内容,如果未能解决你的问题,请参考以下文章
在线程中使用 std::string 函数是不是安全? (c++)