本文介绍了在std :: atomic :: load的结果上使用Structure dereference(->)运算符是否安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试使用std原子指针时,我遇到了以下问题.说我这样做:

Whilst trying to work with std atomic pointer, I ran into the following. Say I do this:

std::atomic<std::string*> myString;
// <do fancy stuff with the string... also on other threads>

//A can I do this?
myString.load()->size()

//B can I do this?
char myFifthChar = *(myString.load()->c_str() + 5);

//C can I do this?
char myCharArray[255];
strcpy(myCharArray, myString.load()->c_str());

我很确定C是非法的,因为同时可能会删除myString.

I'm pretty sure C is illegal because myString might be deleted in the meantime.

但是我不确定A和B.我认为它们是非法的,因为在执行读取操作时可能会引用指针.

However I'm unsure about A and B. I suppose they are illegal since the pointer might be deferenced whilst performing the read operation.

但是,如果是这种情况,您将如何从可能已删除的原子指针中进行读取.由于负载为1步,因此数据读取为1步.

However if this is the case, how can you ever read from an atomic pointer that might be deleted. Since the load is 1 step, and the reading of the data is 1 step.

推荐答案

已提到您的方法是有风险的业务.这里是您可能要考虑的内容:将std::shared_ptr<const std::string>与不可变值一起使用,并且将shared_ptr atomic_load和atomic_store . std::shared_ptr将确保您不会访问悬空的指针,而不变性(构造后字符串不会更改)将确保对字符串本身的访问是线程安全的,因为该标准定义的所有const方法都是线程安全的.安全.

It has been mentioned that your approach is risky business. Here is what you may want to consider instead: Use std::shared_ptr<const std::string> with immutable values, and the shared_ptr atomic_load and atomic_store. std::shared_ptr will ensure you do not access a dangling pointer, while the immutability (string does not change after construction) will guarantee that accesses to the string itself are thread-safe, as all const methods defined by the standard are thread-safe.

根据要求解释危险的生意"的含义:如果您使用std::atomic<std::string *>,则很容易意外引入比赛条件,例如

As requested an explanation of what I mean by "risky business": If you use std::atomic<std::string *>, then it's easy to accidentally introduce race conditions, e.g.

// Data
std::atomic<std::string *> str(new std::string("foo"));

// Thread 1
std::cout << *str.load();

// Thread 2
*str.load() = "bar"; // race condition with read access in thread 1

// Thread 2 (another attempt using immutable instances)
auto newStr = new std::string("bar");
auto oldStr = str.exchange(newStr);
delete oldStr;  /* race condition with read access in thread 1
                   because thread 1 may have performed load() before
                   the exchange became visible to it, and may not
                   be finished using the old object. */

请注意,这与operator <<无关,即使仅在线程1中的字符串上调用size()也会导致竞争状态.

Note that this has nothing to do with operator <<, even just calling size() on the string in thread 1 would lead to the race condition.

在实践中,可能会看到修复程序",例如在不可变字符串的更新中,在delete之前添加sleep,因此线程1有足够的时间完成使用旧指针的业务.尽管这在大多数情况下可能在大多数情况下有效,但它没有引入真正的排序(在C ++标准语言中为 happens-before 关系),因此不是正确的rsp.便携式解决方案.

In practice, one may see "fixes" like adding a sleep before the delete in the update with immutable strings, so that thread 1 has enough time to finish its business with the old pointer. Although this may work most of the time in a particular implementation, it does not introduce a true ordering (a happens-before relation, in C++ standardese) and therefore is not a correct rsp. portable solution.

这篇关于在std :: atomic :: load的结果上使用Structure dereference(-&gt;)运算符是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 08:58