pthread_mutex_lock 和 pthread_mutex_unlock 函数调用内存栅栏/屏障指令?或者 compare_and_swap 隐含的较低级别指令是否存在内存障碍?
答案 0 :(得分:12)
pthread_mutex_lock和pthread_mutex_unlock函数是否调用内存栅栏/屏障指令?
他们这样做,以及线程创建。
但是,请注意,存在两种类型的内存障碍:编译器和硬件。
编译器障碍只会阻止编译器重新排序读写和推测变量值,但不会阻止CPU重新排序。
硬件障碍阻止CPU重新排序读取和写入。全内存栅栏通常是最慢的指令,大多数时候你只需要获取和释放语义的操作(实现自旋锁和互斥锁)。
使用多线程,大多数时候都需要两个障碍。
任何其定义在此转换单元中不可用(并且不是内在的)的函数是编译器内存屏障。 pthread_mutex_lock
,pthread_mutex_unlock
,pthread_create
还会发出硬件内存屏障,以防止CPU重新排序读取和写入。
有关详细信息,请参阅C++ and Beyond 2012: Herb Sutter - atomic<> Weapons。
答案 1 :(得分:11)
请查看POSIX规范的4.11部分。
应用程序应确保限制多个控制线程(线程或进程)对任何内存位置的访问,以便没有控制线程可以读取或修改内存位置,而另一个控制线程可能正在修改它。使用同步线程执行的函数以及相对于其他线程同步内存来限制此类访问。 [强调我的]
然后给出了一个函数列表,它们可以同步内存,还有一些额外的注释。
如果在某些架构上需要内存屏障指令,则必须使用这些指令。
关于compare_and_swap
:不在POSIX中;查看文档以了解您使用的任何内容。例如,IBM defines a compare_and_swap
function for AIX 5.3.没有完整的内存屏障语义文档说明:
如果compare_and_swap用作锁定原语,请在任何关键部分的开头插入isync。
从这个文档我们可以猜到IBM的compare_and_swap
具有发布语义:因为文档不需要为临界区的末尾设置障碍。获取处理器需要发出异步以确保它不读取陈旧数据,但发布处理器不需要做任何事情。
在指令级别,某些处理器已经与某些同步保证进行比较和交换,而有些则没有。