C++ 11引入了标准化的内存模型,但究竟是什么意思呢?它将如何影响C++编程?
这篇文章(引用Herb Sutter的Gavin Clarke)说,
内存模型意味着C++代码现在有一个标准化的库可以调用,无论是谁编译器以及它运行的平台.有一种标准方法可以控制不同线程与处理器内存的对话方式.
"当你谈论在标准中的不同内核之间分割[代码]时,我们正在谈论内存模型.我们将优化它,而不会破坏人们将在代码中做出的以下假设," Sutter说.
好吧,我可以在网上记住这个和类似的段落(因为我从出生以来就拥有自己的记忆模型:P),甚至可以发布作为其他人提出的问题的答案,但说实话,我并不完全明白这个.
C++程序员以前用于开发多线程应用程序,那么如果它是POSIX线程,Windows线程或C++ 11线程,它又如何重要呢?有什么好处?我想了解低级细节.
我也觉得C++ 11内存模型与C++ 11多线程支持有某种关系,因为我经常将这两者结合在一起.如果是,究竟是怎么回事?他们为什么要相关?
由于我不知道多线程的内部工作原理以及内存模型的含义,请帮助我理解这些概念.:-)
曾几何时,为了编写x86汇编程序,你会得到一条说明"加载EDX寄存器的值为5","递增EDX"寄存器等的指令.
对于具有4个核心(甚至更多)的现代CPU,在机器代码级别上它看起来就像有4个独立的CPU(即只有4个不同的"EDX"寄存器)?如果是这样,当你说"递增EDX寄存器"时,是什么决定了哪个CPU的EDX寄存器递增?现在x86汇编程序中是否存在"CPU上下文"或"线程"概念?
核心之间的通信/同步如何工作?
如果您正在编写操作系统,那么通过硬件公开哪种机制可以让您在不同的内核上安排执行?这是一些特殊的特权指示吗?
如果您正在为多核CPU编写优化编译器/字节码VM,那么您需要具体了解x86,以使其生成能够在所有内核中高效运行的代码?
对x86机器代码进行了哪些更改以支持多核功能?
我在Qt的源代码中看到了一些x86程序集:
q_atomic_increment:
movl 4(%esp), %ecx
lock
incl (%ecx)
mov $0,%eax
setne %al
ret
.align 4,0x90
.type q_atomic_increment,@function
.size q_atomic_increment,.-q_atomic_increment
Run Code Online (Sandbox Code Playgroud)
从谷歌搜索,我知道lock指令将导致CPU锁定总线,但我不知道CPU何时释放总线?
关于以上整个代码,我不明白这段代码是如何实现的Add?
我正在研究C++11 中mutex和之间的区别atomic。
据我了解,mutex是一种基于操作系统/内核实现的锁机制。例如,Linux 提供了一种机制,即futex. 在 的帮助下futex,我们可以实现mutex和semaphore。此外,我知道这futex是由低级原子操作实现的,例如CompareAndSet, CompareAndSwap。
对于std::atomic,我知道它是基于C++11引入的内存模型实现的。但是,我不知道内存模型在低级别是如何实现的。如果也是通过原子操作之类CompareAndSet的方式实现的,std::atomic和 和 有mutex什么区别?
总之,如果std::atomic::is_lock_free给我一个false,好吧,我会说这std::atomic与mutex. 但是如果它给了我一个true,它是如何在低级别实现的?
我知道我应该使用volatile关键字告诉编译器不要优化内存read\write到变量.我也知道在大多数情况下它应该只用于与非C++内存通信.
但是,我想知道volatile在持有指向某个本地(堆栈)变量的指针时是否必须使用.
例如:
//global or member variable
/* volatile? */bool* p_stop;
void worker()
{
/* volatile? */ bool stop = false;
p_stop = &stop;
while(!stop)
{
//Do some work
//No usage of "stop" or p_stop" here
}
}
void stop_worker()
{
*p_stop = true;
}
Run Code Online (Sandbox Code Playgroud)
它看起来像一个编译器,有一些优化级别可能会看到这stop是一个局部变量,它永远不会改变,可以替换while(!stop)为a while(true),从而改变*p_stop而什么都不做.
那么,在这种情况下是否需要将指针标记为易失性?
PS:请不要告诉我为什么不使用它,使用这个hack的真正代码是为了(复杂到解释)的原因.
编辑:
我没有提到这两个函数在不同的线程上运行.它worker()是第一个线程的函数,应该使用p_stop指针从另一个线程停止.
我不知道有什么更好的方法来解决这种黑客背后的真正原因.我只是想知道这是否是C++中定义的\未定义的行为(11),如果这是依赖于编译器\ platform\etc的话.到目前为止,我看到@Puppy说每个人都错了,这是错误的,但没有引用表示这个的特定标准.
我知道你们中的一些人被"不要讲我"这一部分所冒犯,但请坚持真正的问题 - 我应该使用volatile与否?或者是这个UB?如果你能提供一个完整的答案,请帮助我(和其他人)学习新的东西.
我是 C++ 并发编程的初学者。我读了 std::atomic_flag ,但我不明白这个 atomic_flag 在哪里有用。也许有人可以解释一下 atomic_flag 对哪些任务有用
我想知道我们是否只是进行加载和存储之间是否有任何std::atomic<int>不同int。我不关心内存顺序。例如考虑下面的代码
int x{1};
void f(int myid) {
while(1){
while(x!= myid){}
//cout<<"thread : "<< myid<<"\n";
//this_thread::sleep_for(std::chrono::duration(3s));
x = (x % 3) + 1;
}
}
int main(){
thread x[3];
for(int i=0;i<3;i++){
x[i] = thread(f,i+1);
}
for(int i=0;i<3;i++){
x[i].join();
}
}
Run Code Online (Sandbox Code Playgroud)
现在输出(如果取消注释 cout)将是
线程:1
螺纹数:2
螺纹数:3
...
int x我想知道更改为有什么好处吗atomic<int> x?