- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
根据C++ Reference , mutex.lock()
是一个 memory_order_acquire
操作,而 mutex.unlock()
是一个 memory_order_release
操作。
但是,memory_order_acquire
和 memory_order_release
仅对非原子和宽松原子操作有效。
memory_order: Release-Acquire ordering on cppreference
If an atomic store in thread A is tagged
memory_order_release
and an atomic load in thread B from the same variable is taggedmemory_order_acquire
, all memory writes (non-atomic and relaxed atomic) that happened-before the atomic store from the point of view of thread A, become visible side-effects in thread B
C++中的互斥体能否保证原子操作的可见性?示例如下。代码A
能否在mu.lock()
之前重新排序,并且线程b
将x
读取为假
?
#include <thread>
#include <atomic>
#include <cassert>
#include <iostream>
#include <unistd.h>
std::atomic<bool> x = {false};
std::mutex mu;
void write_x(){
mu.lock();
std::cout << "write_x" << std::endl;
x.store(true, std::memory_order_release);
mu.unlock();
}
void read_x() {
mu.lock();
std::cout << "read_x" << std::endl;
assert(x.load(std::memory_order_acquire)); // A
mu.unlock();
}
int main() {
std::thread a(write_x);
usleep(1);
std::thread b(read_x);
a.join(); b.join();
return 0;
}
最佳答案
TL:DR:“所有内存写入”表示全部,而不仅仅是提及的类型,但措辞令人困惑。可能只是想指出甚至非原子和宽松的原子操作在同步过程中都是安全可见的,但措辞中缺少“包括”一词。
请注意,cppreference 是一个 wiki,旨在解释该标准。它不是规范性的技术语言,有时甚至用与 ISO C++ 标准不同的术语来解释事物。
它通常非常很好,但不要在某些事情看起来很奇怪时就认为它是完美的。从周围的上下文(和理智)来看,就像段落中的最后一句没有限定条件的“一切”一样,这仍然是相当明显的意思。
ISO C++ 很清楚。 “看到”释放操作的获取操作创建同步关系。 释放之前的所有内容对于获取操作之后的代码都是可见的。
因此,就访问全局一致共享内存状态的操作的模型而言,获取操作会阻止所有内容在它们之前重新排序。包括release和seq_cst操作。 (请注意,cppreference 的这一部分没有提及任何重新排序,只是为了保证可见性。对全局一致状态的访问的本地重新排序实际上是真实 CPU 的工作方式,因此通常以这种方式描述事物更方便,就像您在问题中所做的那样。)
这意味着 C++ 对获取和释放的定义与标准术语相匹配,没有疯狂的神奇异常。 https://preshing.com/20120913/acquire-and-release-semantics/
请注意,有些人使用“宽松原子”来描述所有弱于 seq_cst
的排序。示例:Herb Sutter 在演讲 this question 中就是这样使用的大约是。
这可能就是 cppreference 定义中的含义,但不知道为什么他们要排除 seq_cst
。所有原子和非原子操作都是有序的。所以也许他们的意思是mo_relaxed
,只是想指出甚至这些都是有序/可见的。
(seq_cst
可以说已经对本身进行了排序。其他,所以“当然”它是根据获取和发布操作。但这个原因似乎不太可能。)
如果是为了强调弱阶也由它排序的事实,他们应该写“包括非原子和宽松原子”。如果没有“包括”一词,该措辞可以被理解为暗示仅非原子和宽松原子。只有了解大局以及什么是理智的、什么是不理智的,才能给你正确的解读。
需要准确理解的技术写作经常会使用“包括但不限于”这一短语。
另请注意,您的示例仍然可以触发断言,只是不是出于您担心的原因。
如果线程a
启动缓慢,线程b
可以先进入其临界区并在print+之前打印+读取x
存储在另一个线程中发生。
编写这样的玩具示例的通常方法是一个在获取负载上旋转的循环,直到它看到一个值,例如类似 data_read
的标志,由释放操作在您关心的存储之后存储。这样您就知道读取端在与写入端的释放操作同步的获取操作之后运行。
关于c++ - 可以通过其他获取操作获取负载重新排序吗? cppreference 说只有非原子的和宽松的通过 acquire 排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63543388/
我有一个关于 app.js 的(宽松的)浏览器安全性的问题,因为我在文档中的某个地方读过(我尝试搜索它但找不到它)。我确实看到有一个可以在这里设置的选项: https://github.com/app
我是一名优秀的程序员,十分优秀!