【发布时间】:2020-07-16 20:35:31
【问题描述】:
我所说的足够原子性是指其行为方式与 Linux 地址类型相同。在 Linux 上,如果您有一个代表地址的变量,无论是引用还是指针赋值,都可以保证只能以原子方式观察。
因此您可以执行以下操作。
在某处定义
int *my_ptr = nullptr;
然后在两个单独的线程中你可以得到代码
my_ptr = new int();
和
if (my_ptr) {
*my_ptr = 1;
}
并且一切都应该正常工作,这意味着 my_ptr 不会指向一个垃圾地址,该地址是nullptr 的一半和new int() 返回的地址的一半混合。它要么是nullptr 并且什么都不做,要么是它被初始化并将my_ptr 指向的值设置为1。
我的问题是,如果my_ptr 的类型更改为std::optional<int*> 甚至std::optional<std::wrapped_reference<int>>,同样的属性是否适用?
【问题讨论】:
-
if (my_ptr) { *my_ptr = 1;}-- 这不是原子的。如果在初始测试之后和分配之前,其他一些线程将my_ptr更改为nullptr? -
“在 Linux 上,如果你有一个代表地址的变量,无论是引用还是指针赋值,都只能以原子方式观察。” - 你从哪里学来的?因为那不是真的(或者至少不是你想的那样)。您的整个问题都是基于一个不正确的假设。
-
@PaulMcKenzie 这是一个糟糕的措辞选择。我不知道该怎么称呼这个概念。我只打算设置一次变量,这样就可以了。
-
@SebastianRedl 我找到了提到它的文章,链接在这里。 lwn.net/Articles/262464。这家伙似乎很有名,我认为他不太可能弄错了。然而,这篇文章来自 2007 年。如果您向下滚动到“快速测验 2”,您会看到它被提及。为方便起见,我将在下一条评论中发布摘录。
-
"答案:在所有运行 Linux 的系统上,指针的加载和存储都是原子的,也就是说,如果对指针的存储与从同一指针的加载同时发生,则加载将返回初始值或存储的值,而不是两者的按位混搭。此外,list_for_each_entry_rcu() 总是在列表中前进,从不回头。因此,list_for_each_entry_rcu() 将看到正在添加的元素通过 list_add_rcu(),或者它不会,但无论哪种方式,它都会看到一个有效的格式良好的列表。”