C和C++中未定义,未指定和实现定义的行为有什么区别?
c c++ undefined-behavior unspecified-behavior implementation-defined-behavior
如果有两个线程访问全局变量,那么许多教程都说使变量volatile变为阻止编译器将变量缓存在寄存器中,从而无法正确更新.但是,访问共享变量的两个线程是通过互斥锁来调用保护的东西不是吗?但是在这种情况下,在线程锁定和释放互斥锁之间,代码处于一个关键部分,只有那个线程可以访问变量,在这种情况下变量不需要是volatile?
那么多线程程序中volatile的用途/目的是什么?
我读了一章,我不喜欢它.我还不清楚每个内存顺序之间的差异.这是我目前的推测,我在阅读更简单的http://en.cppreference.com/w/cpp/atomic/memory_order后理解这一点.
以下是错误的,所以不要试图从中学习
a
在另一个线程上放宽了存储.我b
用seq_cst 存储.第三个线程读取a
放松将看到变化以及b
任何其他原子变量? ).如果我错了,我想我理解但是纠正我.我找不到任何用易于阅读的英语解释它的东西.
我需要为另一个线程设置一个标志来退出.另一个线程会不时检查退出标志.我是否必须使用原子作为旗帜或只是一个普通的布尔就足够了(为什么(如果我使用普通布尔可能会出错的例子)?
#include <future>
bool exit = false;
void thread_fn()
{
while(!exit)
{
//do stuff
if(exit) break;
//do stuff
}
}
int main()
{
auto f = std::async(std::launch::async, thread_fn);
//do stuff
exit = true;
f.get();
}
Run Code Online (Sandbox Code Playgroud) https://www.gnu.org/software/libc/manual/html_node/Atomic-Types.html#Atomic-Types说 -在实践中,你可以假设 int 是原子的。你也可以假设指针类型是原子的;那很方便。这两个假设在 GNU C 库支持的所有机器上和我们知道的所有 POSIX 系统上都是正确的。
我的问题是,对于使用 gcc m64 标志编译的 C 程序,是否可以将指针分配视为 x86_64 架构上的原子分配。操作系统为 64 位 Linux,CPU 为 Intel(R) Xeon(R) CPU D-1548。一个线程将设置一个指针,另一个线程将访问该指针。只有一个写入线程和一个读取线程。Reader 应该获取指针的先前值或最新值,并且两者之间没有垃圾值。
如果它不被认为是原子的,请让我知道我如何使用 gcc 原子内置函数或者像 __sync_synchronize 这样的内存屏障来实现相同的效果而不使用锁。只对 C 解决方案感兴趣,对 C++ 不感兴趣。谢谢!
考虑下面的示例是打算等到另一个线程存储42
在一个共享变量shared
没有锁,无需等待线程终止,为什么会volatile T
或std::atomic<T>
会要求或建议,以保证并发正确性?
#include <atomic>
#include <cassert>
#include <cstdint>
#include <thread>
int main()
{
int64_t shared = 0;
std::thread thread([&shared]() {
shared = 42;
});
while (shared != 42) {
}
assert(shared == 42);
thread.join();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用 GCC 4.8.5 和默认选项,示例按预期工作。
假设我有多个线程访问相同的内存位置。而且,如果有的话,它们都写入相同的值,但没有人读取它。之后,所有线程(通过锁)收敛,然后我才读取值。我需要为此使用原子吗?这是针对 x86_64 系统的。该值是一个 int32。
正如我从测试用例中看到的:https : //godbolt.org/z/K477q1
生成的程序集加载/存储原子放松与普通变量相同:ldr 和 str
那么,松弛原子变量和普通变量之间有什么区别吗?
请注意:这只是出于好奇而提出的问题,与编写更好的多线程代码无关。当然,我不会也不会在实际项目中编写这样的代码。
添加关键字时可能会发生内联替换inline
。所以我很好奇。
假设我们有这样的代码:
static bool done = false;
inline void setDone(bool newState) {
done = newState;
}
inline bool getDone() {
return done;
}
void someWorkerThreadJob() {
// Accessing without any lock/atomic/volatile
while (getDone() == false) {
}
}
Run Code Online (Sandbox Code Playgroud)
可以someWorkerThreadJob()
像下面这样编译并进入无限循环吗?
void someThreadJob() {
while (done == false) {
}
}
Run Code Online (Sandbox Code Playgroud)
这也将我引向了下一个问题。类中的getter和setter怎么样?在类中定义的成员函数是隐式的inline
,所以我认为可能会发生内联替换,因此同样的问题。这样对吗?
c++ ×8
atomic ×5
c++11 ×4
c ×3
stdatomic ×3
concurrency ×2
x86-64 ×2
assembly ×1
gcc ×1
implementation-defined-behavior ×1
inline ×1
memory-model ×1
volatile ×1