Atomic 操作時的 memory ordering

Memory ordering 情況主要是 CPU 有快取,如果允許的話,它會由快取拿資料,而不是由記憶體。這有可能造成 CPU A 設了一個值後,CPU B 卻拿快取內的舊值去用的情況。一般來說,memory ordering 在做 lock-free programming 的時候比較要注意。在使用 atomic 操作時,Qt 提供了四種處理 memory ordering 的方式:

  1. Relaxed:不指定 memory ordering,由編譯器及 CPU 決定
  2. Acquire:Qt 官方文件這樣寫,atomic 操作之後的記憶體存取不能在 atoic 操作之前被改變
  3. Release:Qt 官方文件這樣寫,atomic 操作之前的記憶體存取不能在 atoic 操作之後被改變
  4. Ordered:混合 Acquire/Release 兩種方式

官方文件寫得有點看不懂。Acquire 時,CPU 保證我們一定可以正確讀到由其它 CPU 所 "Release" 的寫入。意即我們不會是讀到快取的值,而是真正記憶體的值。而 Release 時,CPU 保證一定會將在這之前寫入快取的值一定會寫入記憶體,讓其它 CPU 可以讀到正確的值。

聽說較少使用的是 Ordered 情境,它在 Q_GLOBAL_STATIC 巨集中有使用。一般來說,似乎使用 Relaxed,單純依 CPU 運作就足夠了,除非我們要寫 lock-free 的同步機制。話說回來,同步機制其實還可以利用 Qt signal-slot 來執行序列化存取的目的。但是 signal-slot 仍要注意如果在 slot 中有建立 event loop,則要注意 slot reentry 的情況。後者是 Qt 不建議使用的方式,但在 porting 一個舊的 C 程式,似乎有時候非常難避免。

參考資料:

留言

熱門文章