内存栅栏(Memory fence),也称为内存屏障(Memory barrier),以前碰到这类概念都是基于锁的理解,比如dispatch_barrier。在看bmalloc的源代码时,发现其在使用原子性(atomic)的时候,出现了一种memory_order
的概念,所以这里来简单看看原子性方面的问题。
Atomic方法
在iOS中,我们平时最常用的原子特性大部分来自于OSAtomic
,可是当我打开这个文件的时候,却发现这些方法已经被弃用了。
1 | OSATOMIC_DEPRECATED_REPLACE_WITH(atomic_compare_exchange_strong) |
很好奇这个新的方法,它来自于C标注库stdatomic.h
中,而这个头文件是C11
才引入的,说明这是一个非常新的方法。而在C++11中,STL增强了C++的多线程编程能力,所以也是这个时候引入的std::atomic
。
atomic
和volidate
,atomic
是真正的原子性,而volidate
则仅标记对象为易变,提交给编译器优化使用的,并不能确保原子性。
Memory Order
1 | typedef enum memory_order { |
关于memory_order
这个概念,非常的令人困惑。其关键就是atomic能够保证单个的操作的原子性,但不能保证两个原子操作之间的顺序,这涉及到CPU对缓存刷新时进行的顺序重排。这里看两个简单的例子就可以理解了:
和我们平时的理解完全不一样,内存的修改顺序和实际的顺序居然可能不一致,这就是为什么会引入memory_order
这个概念了。
Spin lock
最后再来看看SpinLock的实现,所有SpinLock都是基于原子操作进行的,目前我碰到的大致分为两种:
- 比较无赖,强制for循环等待
- 比较友善,在超过一定循环次数,会放弃当前时间片
伪代码:
1 | atomic flag |
所以当某些调度算法,即使是在优先级高的线程中yield放弃时间片,依然不能分配给优先级低的线程,就会导致优先级反转而死锁。
参考
A Tutorial Introduction to the ARM and POWER Relaxed Memory Models