是互斥锁功能没有充分挥发?

的同事,和我写的软件适用于各种在x86,x64上,安腾,PowerPC和其他10岁的服务器CPU上运行的平台。

我们只是有一个关于是否互斥功能,如pthread_mutex_lock()的调用pthread_mutex_unlock ...()是由自己足够,或者是否受保护的变量需要挥发的讨论。

int foo::bar() { //... //code which may or may not access _protected. pthread_mutex_lock(m); int ret = _protected; pthread_mutex_unlock(m); return ret; }

我担心的是缓存。 可以在编译器的地方_protected在栈或寄存器的副本,并使用分配陈旧的价值? 如果没有,是什么阻止这种情况的发生? 此模式的变化脆弱?

我相信,编译器实际上并不明白,pthread_mutex_lock()的是一个特殊的功能,所以我们都只是顺序点保护?

感谢很大。

更新:好吧,我可以看到的答案,解释为什么波动是坏的趋势。 我尊重这些问题的答案,但在这个问题上文章容易在网上找到。 我不能在网上找到,而且我问这个问题的原因,是我没有怎么波动的保护。 如果上面的代码是正确的它是如何无懈可击的缓存问题?

--------------解决方案-------------

如果上面的代码是正确的,它是如何无懈可击的缓存问题?

直到的C ++ 0x,事实并非如此。 而且这还不是在C指定所以,这实际上取决于编译器。 一般情况下,如果编译器不能保证它会尊重排序约束内存访问的功能或涉及多个线程的操作,您将无法编写多线程安全的代码与编译器。 见汉斯·贝姆Ĵ的线程不能被实现为图书馆。

至于什么抽象你的编译器应该为线程安全的代码的支持,在内存壁垒的Wikipedia条目是一个不错的起点。

(至于为什么人建议volatile ,一些编译器把volatile的内存屏障的编译器。这肯定不是标准)。

简单的答案是volatile不需要用于多线程的。

长的答案是一样的关键部分的序列点是与平台相关的是你使用任何线程解决方案让大部分的线程安全性也依赖于平台。

的C ++ 0x有线程和线程安全的概念,但目前的标准并没有因此volatile有时误认为东西,防止操作重新排序和多线程编程的内存访问时,它从来没有打算,不能可靠地使用这种方式。

唯一volatile应在C ++中使用的,是允许访问存储器映射设备,允许的间变量用途setjmplongjmp ,并且允许的用途sig_atomic_t变量信号处理程序。 关键字本身并不能使一个变量原子。

在C ++ 0x的好消息,我们将有STL构造std::atomic可以被用于保证原子操作和线程安全的结构变量。 直到您选择的编译器支持它,你可能需要求助于Boost库或出局一些汇编代码来创建自己的对象为原子变量。

PS很多的混乱是由Java和.NET实际执行多线程语义与关键字造成volatile C ++但是如下用C西装如果是这种情况并非如此。

volatile关键字是一个提示该变量可能会改变程序逻辑,外部如可以作为中断服务程序的一部分,改变内存映射的硬件寄存器中的编译器。 这可以防止假定一个缓存值,编译器始终是正确的,通常会迫使阅读检索值的存储器。 这种用法预先日期由一对夫妇十年左右线程。 我已经看到了它与信号操作,以及使用的变量,但我不肯定的使用是正确的。

读取或不同线程写入时由互斥体把守的变量保证是正确的。 线程API需要确保变量这样的观点是一致的。 这种访问你的程序逻辑的一部分和volatile关键字在这里无关紧要。

你的线程库应包括互斥锁和解锁apropriate CPU和编译器的障碍。 对于GCC,一个memory在asm语句撞作为一个编译器的障碍。

其实,有保护您的代码(编译器)缓存两件事情:

  • 要调用非纯外部函数( pthread_mutex_*()这意味着,编译器不知道该函数不会修改全局变量,因此它必须重新加载它们。
  • 正如我所说, pthread_mutex_*()包括一个编译器障碍,例如:上的glibc / 86 pthread_mutex_lock()最终调用宏lll_lock()其中有一个memory撞,迫使编译器重新加载变量。
分类:C# 时间:2015-03-15 人气:1
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 0.686 (s). 10 q(s)