C++ åèæå
- C++11
- C++14
- C++17
- C++20
- C++ ç¼è¯å¨æ¯ææ åµè¡¨
- ç¬ç«ä¸å®¿ä¸»å®ç°
- C++ è¯è¨
- C++ å ³é®è¯
- é¢å¤çå¨
- C++ æ ååºå¤´æä»¶
- å ·åè¦æ±
- åè½ç¹æ§æµè¯ (C++20)
- å·¥å ·åº
- ç±»åæ¯æï¼åºæ¬ç±»åãRTTIãç±»åç¹æ§ï¼
- æ¦å¿µåº (C++20)
- é误å¤ç
- 卿å å管ç
- æ¥æåæ¶é´å·¥å ·
- å符串åº
- 容å¨åº
- è¿ä»£å¨åº
- èå´åº (C++20)
- ç®æ³åº
- æ°å¼åº
- è¾å ¥/è¾åºåº
- æä»¶ç³»ç»åº
- æ¬å°ååº
- æ£å表达å¼åº
- ååæä½åº
- std::atomic_store, std::atomic_store_explicit
- std::atomic_load, std::atomic_load_explicit
- std::atomic_exchange, std::atomic_exchange_explicit
- std::atomic
- std::atomic_flag
- std::atomic_ref
- std::atomic_compare_exchange_weak, std::atomic_compare_exchange_strong, std::atomic_compare_exchange_weak_explicit, std::atomic_compare_exchange_strong_explicit
- std::atomic_fetch_add, std::atomic_fetch_add_explicit
- std::atomic_fetch_sub, std::atomic_fetch_sub_explicit
- std::atomic_fetch_and, std::atomic_fetch_and_explicit
- std::atomic_fetch_or, std::atomic_fetch_or_explicit
- std::atomic_fetch_xor, std::atomic_fetch_xor_explicit
- std::atomic_is_lock_free, ATOMIC_xxx_LOCK_FREE
- std::atomic_wait, std::atomic_wait_explicit
- std::atomic_notify_one
- std::atomic_notify_all
- std::atomic_flag_test_and_set, std::atomic_flag_test_and_set_explicit
- std::atomic_flag_clear, std::atomic_flag_clear_explicit
- std::atomic_flag_test, std::atomic_flag_test_explicit
- std::atomic_flag_wait, std::atomic_flag_wait_explicit
- std::atomic_flag_notify_one
- std::atomic_flag_notify_all
- std::atomic_init
- ATOMIC_VAR_INIT
- ATOMIC_FLAG_INIT
- std::memory_order
- std::kill_dependency
- std::atomic_thread_fence
- std::atomic_signal_fence
- 注é
- çº¿ç¨æ¯æåº
- å®éªæ§ C++ ç¹æ§
- æç¨çèµæº
- ç´¢å¼
- std 符å·ç´¢å¼
- åç¨æ¯æ (C++20)
- C++ å ³é®è¯
ä½ç½®ï¼é¦é¡µ > C++ åèæå >ååæä½åº > std::memory_order
std::memory_order
  memory_order_relaxed,
  memory_order_consume,
  memory_order_acquire,
  memory_order_release,
  memory_order_acq_rel,
  memory_order_seq_cst
(C++20 å)
  relaxed, consume, acquire, release, acq_rel, seq_cst
};
inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
inline constexpr memory_order memory_order_consume = memory_order::consume;
inline constexpr memory_order memory_order_acquire = memory_order::acquire;
inline constexpr memory_order memory_order_release = memory_order::release;
inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
std::memory_order æå®å
å访é®ï¼å
æ¬å¸¸è§çéååå
å访é®ï¼å¦ä½å´ç»ååæä½æåºã卿²¡æä»»ä½å¶çº¦çå¤å¤çå¨ç³»ç»ä¸ï¼å¤ä¸ªçº¿ç¨åæ¶è¯»æåæ°ä¸ªåéæ¶ï¼ä¸ä¸ªçº¿ç¨è½è§æµå°åé弿´æ¹ç顺åºä¸åäºå¦ä¸ä¸ªçº¿ç¨åå®ä»¬ç顺åºãå
¶å®ï¼æ´æ¹ç顺åºçè³è½å¨å¤ä¸ªè¯»å线ç¨é´ç¸å¼ãä¸äºç±»ä¼¼çææè¿è½å¨åå¤çå¨ç³»ç»ä¸åºç°ï¼å 为å
忍¡åå
许ç¼è¯å¨åæ¢ã
åºä¸ææååæä½çé»è®¤è¡ä¸ºæä¾åºåä¸è´é¡ºåºï¼è§å述讨论ï¼ã该é»è®¤è¡ä¸ºå¯è½æææ§è½ï¼ä¸è¿å¯ä»¥ç»äºåºçååæä½é¢å¤ç std::memory_order åæ°ï¼ä»¥æå®éå å¶çº¦ï¼å¨ååæ§å¤ï¼ç¼è¯å¨åå¤çå¨è¿å¿
须强å¶è¯¥æä½ã
常é
| å®ä¹äºå¤´æä»¶
<atomic> | |
| Â | |
| å¼ | è§£é |
memory_order_relaxed
|
å®½æ¾æä½ï¼æ²¡æåæ¥æé¡ºåºå¶çº¦ï¼ä» å¯¹æ¤æä½è¦æ±ååæ§ï¼è§ä¸æ¹å®½æ¾é¡ºåºï¼ã |
memory_order_consume
|
ææ¤å å顺åºçå è½½æä½ï¼å¨å ¶å½±åçå åä½ç½®è¿è¡æ¶è´¹æä½ï¼å½å线ç¨ä¸ä¾èµäºå½åå è½½ç该å¼ç读æåä¸è½è¢«éæå°æ¤å è½½åãå ¶ä»éæ¾åä¸åååéç线ç¨çå¯¹æ°æ®ä¾èµåéçåå ¥ï¼ä¸ºå½åçº¿ç¨æå¯è§ãå¨å¤§å¤æ°å¹³å°ä¸ï¼è¿åªå½±åå°ç¼è¯å¨ä¼åï¼è§ä¸æ¹éæ¾æ¶è´¹é¡ºåºï¼ã |
memory_order_acquire
|
ææ¤å å顺åºçå è½½æä½ï¼å¨å ¶å½±åçå åä½ç½®è¿è¡è·å¾æä½ï¼å½å线ç¨ä¸è¯»æåä¸è½è¢«éæå°æ¤å è½½åãå ¶ä»éæ¾åä¸åååéç线ç¨çææåå ¥ï¼è½ä¸ºå½åçº¿ç¨æè§ï¼è§ä¸æ¹éæ¾è·å¾é¡ºåºï¼ã |
memory_order_release
|
ææ¤å å顺åºçå卿ä½è¿è¡éæ¾æä½ï¼å½å线ç¨ä¸ç读æåä¸è½è¢«éæå°æ¤åå¨åãå½å线ç¨çææåå ¥ï¼å¯è§äºè·å¾è¯¥åä¸åååéçå ¶ä»çº¿ç¨éæ¾è·å¾é¡ºåºï¼ï¼å¹¶ä¸å¯¹è¯¥åååéç带ä¾èµåå ¥åå¾å¯¹äºå ¶ä»æ¶è´¹åä¸åå对象ç线ç¨å¯è§ï¼è§ä¸æ¹éæ¾æ¶è´¹é¡ºåºï¼ã |
memory_order_acq_rel
|
带æ¤å å顺åºç读修æ¹åæä½æ¢æ¯è·å¾æä½åæ¯éæ¾æä½ãå½å线ç¨ç读æåå åä¸è½è¢«éæå°æ¤åå¨åæåãææéæ¾åä¸åååéç线ç¨çåå ¥å¯è§äºä¿®æ¹ä¹åï¼èä¸ä¿®æ¹å¯è§äºå ¶ä»è·å¾åä¸åååéç线ç¨ã |
memory_order_seq_cst
|
ææ¤å å顺åºçå è½½æä½è¿è¡è·å¾æä½ï¼å卿ä½è¿è¡éæ¾æä½ï¼è读修æ¹åæä½è¿è¡è·å¾æä½åéæ¾æä½ï¼åå ä¸åå¨ä¸ä¸ªåç¬å ¨åºï¼å ¶ä¸ææçº¿ç¨ä»¥åä¸é¡ºåºè§æµå°ææä¿®æ¹ï¼è§ä¸æ¹åºåä¸è´é¡ºåºï¼ã |
æ£å¼æè¿°
线ç¨é´åæ¥åå å顺åºå³å®è¡¨è¾¾å¼çæ±å¼å坿åºå¨ç¨åºæ§è¡çä¸å线ç¨é´å¦ä½æåºãå®ä»¬ä»¥ä¸å项ç®å®ä¹ï¼
å åºäº
å¨åä¸çº¿ç¨ä¸ï¼æ±å¼ A å¯ä»¥å åºäºæ±å¼ B ï¼å¦æ±å¼é¡ºåºä¸ææè¿°ã
æºå¸¦ä¾èµ
å¨åä¸çº¿ç¨ä¸ï¼è¥ä¸åä»»ä¸ä¸ºçï¼åå åºäºæ±å¼ B çæ±å¼ A 亦å¯å°ä¾èµå¸¦å ¥ B ï¼å³ B ä¾èµäº A ï¼
ä¿®æ¹é¡ºåº
对任ä½ç¹å®çåååéçä¿®æ¹ï¼ä»¥éå®äºæ¤ä¸åååéçåç¬å ¨åºåºç°ã
对ææååæä½ä¿è¯ä¸ååä¸ªè¦æ±ï¼
éæ¾åºå
å¨åå对象 M ä¸è¿è¡çéæ¾æä½ A ä¹åï¼ç±ä¸åå å®¹ç»æç M ä¿®æ¹é¡ºåºçæé¿ç¸æ¥ååºå
|
1) ä¸è¿è¡ A çåä¸çº¿ç¨æè¿è¡çåå
¥
|
(C++20 å) |
被称为 A æå¼é¢çéæ¾åºåã
ä¾èµå åºäº
å¨çº¿ç¨é´ï¼è¥ä¸åä»»ä¸ä¸ºçï¼åæ±å¼ A ä¾èµå åºäºæ±å¼ B
线ç¨é´å åçäº
å¨çº¿ç¨é´ï¼è¥ä¸åä»»ä¸ä¸ºçï¼åæ±å¼ A 线ç¨é´å åçäºæ±å¼ B
å åçäº
æ å ³ä¹çº¿ç¨ï¼è¥ä¸åä»»ä¸ä¸ºçï¼åæ±å¼ A å åçäºæ±å¼ B ï¼
è¦æ±å®ç°ç¡®ä¿å åçäºå ³ç³»æ¯é循ç¯çï¼è¥æå¿ è¦åå¼å ¥é¢å¤ç忥ï¼è¥å¼å ¥æ¶è´¹æä½ï¼å®æå¯è½ä¸ºå¿ è¦ï¼è§ Batty çï¼ã
è¥ä¸æ¬¡æ±å¼ä¿®æ¹ä¸ä¸ªå åä½ç½®ï¼èå ¶ä»æ±å¼è¯»æä¿®æ¹åä¸å åä½ç½®ï¼ä¸è³å°ä¸ä¸ªæ±å¼ä¸æ¯ååæä½ï¼åç¨åºçè¡ä¸ºæªå®ä¹ï¼ç¨åºææ°æ®ç«äºï¼ï¼é¤éè¿ä¸¤ä¸ªæ±å¼ä¹é´åå¨å åçäºå ³ç³»ã
ç®åå åçäºæ å ³ä¹çº¿ç¨ï¼è¥ä¸åä¹ä¸ä¸ºçï¼åæ±å¼ A ç®åå åçäºæ±å¼ B ï¼ 1) A å
åºäº B
2) A åæ¥äº B
3) A ç®åå
åçäº X ï¼è X ç®åå
åçäº B
注ï¼ä¸è®¡æ¶è´¹æä½ï¼åç®åå åçäºä¸å¼ºå åçäºå ³ç³»æ¯ç¸åçã |
(C++20 èµ·) |
强å åçäº
æ å ³ä¹çº¿ç¨ï¼è¥ä¸åä¹ä¸ä¸ºçï¼åæ±å¼ A 强å åçäºæ±å¼ B ï¼
|
1) A å
åºäº B
2) A åæ¥äº B
3) A 强å
åçäº X ï¼è X 强å
åçäº B
|
(C++20 å) |
|
1) A å
åºäº B
2) A åæ¥äº B ï¼ä¸ A ä¸ B å为åºåä¸è´çååæä½
3) A å
åºäº X ï¼ X ç®åå
åçäº Y ï¼è Y å
åºäº B
4) A 强å
åçäº X ï¼è X 强å
åçäº B
注ï¼éæ£å¼èè¨ï¼è¥ A 强å åçäº B ï¼å卿æç¯å¢ä¸ A åæ¾å¾å¨ B ä¹åå¾å°æ±å¼ã 注ï¼å¼ºå åçäºæé¤æ¶è´¹æä½ã |
(C++20 èµ·) |
å¯è§å¯æåº
è¥ä¸åç为çï¼åæ é M ä¸çå¯æåº A ï¼åå ¥ï¼ç¸å¯¹äº M ä¸çå¼è®¡ç®ï¼è¯»åï¼å¯è§ï¼
è¥å¯æåº A ç¸å¯¹äºå¼è®¡ç® B å¯è§ï¼åä¿®æ¹é¡ºåºä¸ï¼æ»¡è¶³ B ä¸å åçäºå®ç对 M ç坿åºçæé¿ç¸æ¥åéï¼è¢«ç§°ä¸ºå¯æåºçå¯è§åºåãï¼ B æç¡®å®ç M çå¼ï¼å°æ¯è¿äºå¯æåºä¹ä¸æåå¨çå¼ï¼
注æï¼çº¿ç¨é´åæ¥å¯å½ç»ä¸ºé¿å æ°æ®ç«äºï¼éè¿å»ºç«å åçäºå ³ç³»ï¼ï¼åå®ä¹å¨ä½ç§æ¡ä»¶ä¸åªäºå¯æåºæä¸ºå¯è§ã
æ¶è´¹æä½
带 memory_order_consume ææ´å¼ºæ ç¾çååå卿¯æ¶è´¹æä½ã注æ std::atomic_thread_fence 伿½å æ¯æ¶è´¹æä½æ´å¼ºçåæ¥è¦æ±ã
è·å¾æä½
带 memory_order_acquire ææ´å¼ºæ ç¾çååå卿¯è·å¾æä½ãäºæ¥ä½ (Mutex) ä¸ç lock() æä½äº¦ä¸ºè·å¾æä½ã注æ std::atomic_thread_fence 伿½å æ¯è·å¾æä½æ´å¼ºçåæ¥è¦æ±ã
éæ¾æä½
带 memory_order_release ææ´å¼ºæ ç¾çååå卿¯éæ¾æä½ãäºæ¥ä½ (Mutex) ä¸ç unlock() æä½äº¦ä¸ºéæ¾æä½ã注æ std::atomic_thread_fence 伿½å æ¯éæ¾æä½æ´å¼ºçåæ¥è¦æ±ã
è§£é
宽æ¾é¡ºåº
带æ ç¾ memory_order_relaxed çååæä½æ 忥æä½ï¼å®ä»¬ä¸ä¼å¨å ±æ¶çå å访é®é´å¼ºå 顺åºãå®ä»¬åªä¿è¯ååæ§åä¿®æ¹é¡ºåºä¸è´æ§ã
ä¾å¦ï¼å¯¹äºæå为é¶ç x å y ï¼
// çº¿ç¨ 1 ï¼ r1 = y.load(std::memory_order_relaxed); // A x.store(r1, std::memory_order_relaxed); // B // çº¿ç¨ 2 ï¼ r2 = x.load(std::memory_order_relaxed); // C y.store(42, std::memory_order_relaxed); // D
å
许产çç»æ r1 == 42 && r2 == 42 ï¼å 为å³ä½¿çº¿ç¨ 1 ä¸ A å
åºäº B ä¸çº¿ç¨ 2 ä¸ C å
åºäº D ï¼å´æ²¡æå¶çº¦é¿å
y çä¿®æ¹é¡ºåºä¸ D å
åºç°äº A ï¼è x çä¿®æ¹é¡ºåºä¸ B å
åºç°äº C ã D å¨ y ä¸ç坿åºï¼å¯è½å¯è§äºçº¿ç¨ 1 ä¸çå è½½ A ï¼åæ¶ B å¨ x ä¸ç坿åºï¼å¯è½å¯è§äºçº¿ç¨ 2 ä¸çå è½½ C ã
|
å³ä½¿ä½¿ç¨å®½æ¾å
忍¡åï¼ä¹ä¸å
è®¸âæ ä¸çæâçå¼å¾ªç¯å°ä¾èµäºå
¶åèªç计ç®ï¼ä¾å¦ï¼å¯¹äºæå为é¶ç // 线ç¨1ï¼ r1 = x.load(std::memory_order_relaxed); if (r1 == 42) y.store(r1, std::memory_order_relaxed); // 线ç¨2ï¼ r2 = y.load(memory_order_relaxed); if (r2 == 42) x.store(42, std::memory_order_relaxed); ä¸å
许产çç»æ |
(C++14 èµ·) |
宽æ¾å å顺åºçå ¸åä½¿ç¨æ¯è®¡æ°å¨èªå¢ï¼ä¾å¦ std::shared_ptr çå¼ç¨è®¡æ°å¨ï¼å 为è¿åªè¦æ±ååæ§ï¼ä½ä¸è¦æ±é¡ºåºæåæ¥ï¼æ³¨æ std::shared_ptr 计æ°å¨èªåè¦æ±ä¸ææå½æ°è¿è¡è·å¾éæ¾åæ¥ï¼
#include <vector> #include <iostream> #include <thread> #include <atomic> Â std::atomic<int> cnt = {0}; Â void f() { for (int n = 0; n < 1000; ++n) { cnt.fetch_add(1, std::memory_order_relaxed); } } Â int main() { std::vector<std::thread> v; for (int n = 0; n < 10; ++n) { v.emplace_back(f); } for (auto& t : v) { t.join(); } std::cout << "Final counter value is " << cnt << '\n'; }
è¾åºï¼
Final counter value is 10000
éæ¾è·å¾é¡ºåº
è¥çº¿ç¨ A ä¸çä¸ä¸ªåååå¨å¸¦æ ç¾ memory_order_release ï¼èçº¿ç¨ B 䏿¥èªåä¸åéçååå 载带æ ç¾ memory_order_acquire ï¼åä»çº¿ç¨ A çè§è§å åçäºåååå¨çææå ååå ¥ï¼éååå宽æ¾ååçï¼ï¼å¨çº¿ç¨ B ä¸æä¸ºå¯è§å¯æåºï¼å³ä¸æ¦ååå è½½å®æï¼åä¿è¯çº¿ç¨ B è½è§å¯å°çº¿ç¨ A åå ¥å åçææå 容ã
åæ¥ä» å»ºç«å¨éæ¾åè·å¾åä¸åå对象ç线ç¨ä¹é´ãå ¶ä»çº¿ç¨å¯è½çå°ä¸è¢«åæ¥çº¿ç¨çä¸è æä¸¤è ç¸å¼çå å访é®é¡ºåºã
å¨å¼ºé¡ºåºç³»ç»ï¼ x86 ã SPARC TSO ã IBM ä¸»æ¡æ¶ï¼ä¸ï¼éæ¾è·å¾é¡ºåºå¯¹äºå¤æ°æä½æ¯èªå¨è¿è¡çãæ é为æ¤åæ¥æ¨¡å¼æ·»å é¢å¤ç CPU æä»¤ï¼åªææäºç¼è¯å¨ä¼ååå½±åï¼ä¾å¦ï¼ç¼è¯å¨è¢«ç¦æ¢å°éåååå¨ç§»å°åååå¨-éæ¾åï¼æå°éååå 载移å°ååå è½½-è·å¾åï¼ãå¨å¼±é¡ºåºç³»ç»ï¼ ARM ã Itanium ã Power PC ï¼ä¸ï¼å¿ 须使ç¨ç¹å«ç CPU å è½½æå åæ æ æä»¤ã
äºæ¥éï¼ä¾å¦ std::mutex æååèªæéï¼æ¯éæ¾è·å¾åæ¥çä¾åï¼çº¿ç¨ A éæ¾éèçº¿ç¨ B è·å¾å®æ¶ï¼åçäºçº¿ç¨ A ç¯å¢ç临çåºï¼éæ¾ä¹åï¼ä¸çææäºä»¶ï¼å¿ é¡»å¯¹äºæ§è¡åä¸ä¸´çåºççº¿ç¨ B ï¼è·å¾ä¹åï¼å¯è§ã
#include <thread> #include <atomic> #include <cassert> #include <string>  std::atomic<std::string*> ptr; int data;  void producer() { std::string* p = new std::string("Hello"); data = 42; ptr.store(p, std::memory_order_release); }  void consumer() { std::string* p2; while (!(p2 = ptr.load(std::memory_order_acquire))) ; assert(*p2 == "Hello"); // ç»æ é®é¢ assert(data == 42); // ç»æ é®é¢ }  int main() { std::thread t1(producer); std::thread t2(consumer); t1.join(); t2.join(); }
ä¸ä¾æ¼ç¤ºä¸ä¸ªçº¿ç¨é´ä¼ éæ§çéæ¾è·å¾é¡ºåº
#include <thread> #include <atomic> #include <cassert> #include <vector>  std::vector<int> data; std::atomic<int> flag = {0};  void thread_1() { data.push_back(42); flag.store(1, std::memory_order_release); }  void thread_2() { int expected=1; while (!flag.compare_exchange_strong(expected, 2, std::memory_order_acq_rel)) { expected = 1; } }  void thread_3() { while (flag.load(std::memory_order_acquire) < 2) ; assert(data.at(0) == 42); // å³ä¸åºé }  int main() { std::thread a(thread_1); std::thread b(thread_2); std::thread c(thread_3); a.join(); b.join(); c.join(); }
éæ¾æ¶è´¹é¡ºåº
è¥çº¿ç¨ A ä¸çåååå¨å¸¦æ ç¾ memory_order_release èçº¿ç¨ B 䏿¥èªåä¸åå对象çå 载带æ ç¾ memory_order_consume ï¼åçº¿ç¨ A è§è§ä¸ä¾èµå åºäºåååå¨çææå ååå ¥ï¼éååå宽æ¾ååçï¼ï¼ä¼å¨çº¿ç¨ B ä¸è¯¥å è½½æä½ææºå¸¦ä¾èµè¿å ¥çæä½ä¸åæå¯è§å¯æåºï¼å³ä¸æ¦å®æååå è½½ï¼åä¿è¯çº¿ç¨Bä¸ï¼ä½¿ç¨ä»è¯¥å è½½è·å¾çå¼çè¿ç®ç¬¦å彿°ï¼è½è§å°çº¿ç¨ A åå ¥å åçå 容ã
åæ¥ä» å¨éæ¾åæ¶è´¹åä¸åå对象ç线ç¨é´å»ºç«ãå ¶ä»çº¿ç¨è½è§å°ä¸è¢«åæ¥çº¿ç¨çä¸è æä¸¤è ç¸å¼çå å访é®é¡ºåºã
ææå¼äº DEC Alpha çä¸»æµ CPU ä¸ï¼ä¾èµé¡ºåºæ¯èªå¨çï¼æ é为æ¤åæ¥æ¨¡å¼äº§çéå ç CPU æä»¤ï¼åªææäºç¼è¯å¨ä¼åæ¶çåå½±åï¼ä¾å¦ï¼ç¼è¯å¨è¢«ç¦æ¢çµæ¶å°ä¾èµé¾ç对象ä¸çæ¨æµæ§å è½½ï¼ã
æ¤é¡ºåºçå ¸åä½¿ç¨æ åµï¼æ¶å对å¾å°è¢«åå ¥çæ°æ®ç»æï¼å®æè¡¨ãé ç½®ãå®å ¨çç¥ãé²ç«å¢è§åçï¼çå ±æ¶è¯»åï¼åææéä¸ä»åå¸çåå¸è -订é è æ å½¢ï¼å³å½ç产è å叿¶è´¹è è½éè¿å ¶è®¿é®ä¿¡æ¯çæé乿¶ï¼æ é令ç产è åå ¥å åçææå ¶ä»å 容对æ¶è´¹è å¯è§ï¼è¿å¨å¼±é¡ºåºæ¶æä¸å¯è½æ¯æè´µçæä½ï¼ãè¿ç§åºæ¯çä¾åä¹ä¸æ¯ rcu è§£å¼ç¨ã
ç»ç²åº¦ä¾èµé¾æ§å¶å¯åé
std::kill_dependency å [[carries_dependency]] ã
注æå° 2015 å¹´ 2 æä¸ºæ¢æ²¡æäº§åç¼è¯å¨è·è¸ªä¾èµé¾ï¼åå°æ¶è´¹æä½æå为è·å¾æä½ã
|
éæ¾æ¶è´¹é¡ºåºçè§èæ£å¨ä¿®è®¢ä¸ï¼è䏿æ¶ä¸é¼å±ä½¿ç¨ |
(C++17 èµ·) |
æ¤ç¤ºä¾æ¼ç¤ºç¨äºæéä¸ä»çåå¸çä¾èµå®åºåæ¥ï¼int dataä¸ç±æ°æ®ä¾èµå ³ç³»å ³èå°æåå符串çæéï¼ä»èå ¶å¼å¨æ¶è´¹è 䏿ªå®ä¹ã
#include <thread> #include <atomic> #include <cassert> #include <string>  std::atomic<std::string*> ptr; int data;  void producer() { std::string* p = new std::string("Hello"); data = 42; ptr.store(p, std::memory_order_release); }  void consumer() { std::string* p2; while (!(p2 = ptr.load(std::memory_order_consume))) ; assert(*p2 == "Hello"); // ç»æ åºéï¼ *p2 ä» ptr æºå¸¦ä¾èµ assert(data == 42); // å¯è½ä¹å¯è½ä¸ä¼åºéï¼ data ä¸ä» ptr æºå¸¦ä¾èµ }  int main() { std::thread t1(producer); std::thread t2(consumer); t1.join(); t2.join(); }
åºåä¸è´é¡ºåº
带æ ç¾ memory_order_seq_cst çååæä½ä¸ä» 以ä¸éæ¾/è·å¾é¡ºåºç¸åçæ¹å¼æåºå åï¼å¨ä¸ä¸ªçº¿ç¨ä¸å åçäºåå¨çä»»ä½ç»æé½åæè¿è¡å è½½ç线ç¨ä¸çå¯è§å¯æåºï¼ï¼è¿å¯¹ææå¸¦æ¤æ ç¾çå åæä½å»ºç«åç¬å ¨åºã
|
æ£å¼èè¨ï¼ æ¯ä¸ªå è½½åå对象 M ç
è¥åå¨
设æä¸å¯¹ M ä¸çååæä½ï¼ç§°ä¹ä¸º A å B ï¼è¿é A åå
¥ã B 读å M çå¼ï¼è¥åå¨äºä¸ª
设æä¸å¯¹ M ä¸çååæä½ï¼ç§°ä¹ä¸º A å B ï¼è¥ç¬¦åä¸åæ¡ä»¶ä¹ä¸ï¼å M çä¿®æ¹é¡ºåºä¸ B å åçäº A
注æè¿è¡¨æï¼ 1) åªè¦ä¸å¸¦
memory_order_seq_cst æ ç¾çååæä½è¿å
¥å±é¢ï¼åç«å³ä¸§å¤±åºåä¸è´æ§2) åºåä¸è´æ
æ ä»
为æ
æ èªèº«å»ºç«å
¨åºï¼èä¸ä¸ºé常æ
åµä¸çååæä½å»ºç«ï¼å
åºäºä¸æ¯è·¨çº¿ç¨å
³ç³»ï¼ä¸åäºå
åçäºï¼
|
(C++20 å) |
|
æ£å¼èè¨ï¼ æåå对象 M ä¸çååæä½è¿è´¯å åºäº M ä¸çå¦ä¸ååæä½ B ï¼è¥ä¸åä»»ä¸ä¸ºçï¼ 1) A æ¯ä¿®æ¹ï¼è B 读å A æåå¨çå¼
2) A å¨ M çä¿®æ¹é¡ºåºä¸åäº B
3) A 读åååæä½ X æåå¨çå¼ï¼è X å¨ä¿®æ¹é¡ºåºä¸åäº B ï¼ä¸ A ä¸ B 䏿¯åä¸è¯»ä¿®æ¹åæä½
4) A è¿è´¯å
åºäº X ï¼è X è¿è´¯å
åºäº B
ææ 1) è¥ A ä¸ B 为
memory_order_seq_cst æä½ï¼è A 强å
åçäº B ï¼å A å¨ S ä¸åäº B2) 对äºå¯¹è±¡ M ä¸çæ¯å¯¹ååæä½ A ä¸ B ï¼å
¶ä¸ A è¿è´¯å
åºäº B ï¼
a) è¥ A ä¸ B 齿¯
memory_order_seq_cst æä½ï¼å S ä¸ A åäº Bb) è¥ A æ¯
memory_order_seq_cst æä½ï¼è B å
åçäº memory_order_seq_cst æ
æ Y ï¼å S ä¸ A åäº Yc) è¥
memory_order_seq_cst æ
æ X å
åçäº A ï¼è B 为 memory_order_seq_cst æä½ï¼å S ä¸ X åäº Bd) è¥
memory_order_seq_cst æ
æ X å
åçäº A ï¼è B å
åçäº memory_order_seq_cst æ
æ Y ï¼å S ä¸ X åäº Yæ£å¼å®ä¹ç¡®ä¿ï¼ 1) åç¬å
¨åºä¸ä»»ä½åå对象çä¿®æ¹é¡ºåºä¸è´
2)
memory_order_seq_cst å è½½ä»æåç memory_order_seq_cst ä¿®æ¹ï¼æä»æä¸ªä¸å
åçäºé¡ºåºä¸ä¹åç memory_order_seq_cst ä¿®æ¹æä½çé memory_order_seq_cst ä¿®æ¹ä¹ä¸è·åå
¶å¼ãåç¬å
¨åºå¯è½ä¸å
åçäºä¸ä¸è´ãè¿å
许 ä¾å¦ï¼å¯¹äºåå¼ä¸ºé¶ç // çº¿ç¨ 1 ï¼ x.store(1, std::memory_order_seq_cst); // A y.store(1, std::memory_order_release); // B // çº¿ç¨ 2 ï¼ r1 = y.fetch_add(1, std::memory_order_seq_cst); // C r2 = y.load(std::memory_order_relaxed); // D // çº¿ç¨ 3 ï¼ y.store(3, std::memory_order_seq_cst); // E r3 = x.load(std::memory_order_seq_cst); // F å
许è¿äºæä½äº§ç 注æï¼ 1) 䏿¦ä¸å¸¦
memory_order_seq_cst æ ç¾çååæä½è¿å
¥å±é¢ï¼ç¨åºçåºåä¸è´ä¿è¯å°±ä¼ç«å³ä¸§å¤±2) 夿°æ
åµä¸ï¼ memory_order_seq_cst ååæä½ç¸å¯¹äºåä¸çº¿ç¨æè¿è¡çå
¶ä»ååæä½å¯éæ
|
(C++20 èµ·) |
è¥å¨å¤ç产è -夿¶è´¹è çæ å½¢ä¸ï¼ä¸æææ¶è´¹è é½å¿ 须以ç¸å顺åºè§å¯å°ææç产è çå¨ä½åºç°ï¼åå¯è½å¿ é¡»æåºå顺åºã
å ¨åºå顺åºå¨ææå¤æ ¸ç³»ç»ä¸è¦æ±å®å ¨çå åæ æ CPU æä»¤ãè¿å¯è½æä¸ºæ§è½ç¶é¢ï¼å 为å®å¼ºå¶åå½±åçå å访é®ä¼ æå°æ¯ä¸ªæ ¸å¿ã
æ¤ç¤ºä¾æ¼ç¤ºåºåä¸ç´é¡ºåºä¸ºå¿
è¦çåºåãä»»ä½å
¶ä»é¡ºåºé½å¯è½è§¦åassertï¼å 为å¯è½ä»¤çº¿ç¨cådè§æµå°åå对象xåy以ç¸åé¡ºåºæ´æ¹ã
#include <thread> #include <atomic> #include <cassert>  std::atomic<bool> x = {false}; std::atomic<bool> y = {false}; std::atomic<int> z = {0};  void write_x() { x.store(true, std::memory_order_seq_cst); }  void write_y() { y.store(true, std::memory_order_seq_cst); }  void read_x_then_y() { while (!x.load(std::memory_order_seq_cst)) ; if (y.load(std::memory_order_seq_cst)) { ++z; } }  void read_y_then_x() { while (!y.load(std::memory_order_seq_cst)) ; if (x.load(std::memory_order_seq_cst)) { ++z; } }  int main() { std::thread a(write_x); std::thread b(write_y); std::thread c(read_x_then_y); std::thread d(read_y_then_x); a.join(); b.join(); c.join(); d.join(); assert(z.load() != 0); // å³ä¸åç }
ä¸ volatile çå ³ç³»
卿§è¡çº¿ç¨ä¸ï¼ä¸è½å°éè¿ volatile æ³å·¦å¼ç访é®ï¼è¯»ååï¼éæå°å线ç¨å å åºäºæååºäºå®çå¯è§æµå¯æåºï¼å å«å ¶ä» volatile 访é®ï¼åï¼ä½ä¸ä¿è¯å¦ä¸çº¿ç¨è§å¯å°æ¤é¡ºåºï¼å 为 volatile 访é®ä¸å»ºç«çº¿ç¨é´åæ¥ã
å¦å¤ï¼ volatile 访é®ä¸æ¯ååçï¼å ±æ¶ç读ååæ¯æ°æ®ç«äºï¼ï¼ä¸ä¸æåºå åï¼é volatile å å访é®å¯ä»¥èªç±å°éæå° volatile 访é®ååï¼ã
ä¸ä¸ªå¼å¾æ³¨æçä¾å¤æ¯ Visual Studio ï¼å ¶ä¸é»è®¤è®¾ç½®ä¸ï¼æ¯ä¸ª volatile 忥æéæ¾è¯ä¹ï¼èæ¯ä¸ª volatile è¯»æ¥æè·å¾è¯ä¹ï¼ MSDN ï¼ï¼æ èå¯å° volatile 对象ç¨äºçº¿ç¨é´åæ¥ãæ åç volatile è¯ä¹ä¸å¯åºç¨äºå¤çº¿ç¨ç¼ç¨ï¼å°½ç®¡å®ä»¬å¨åºç¨å° sig_atomic_t 对象æ¶ï¼è¶³ä»¥ä¸ä¾å¦è¿è¡äºåä¸çº¿ç¨ç std::signal å¤ç彿°äº¤æµã
åé
å¤é¨é¾æ¥
| æ¬èæªå®æ åå ï¼æä»¬å¨ QPI ã MOESI å¯è½è¿æ Dragon 䏿¾ä¸å¥½åè |
- x86-TSO ï¼ x86 å¤å¤çå¨ä¸ä¸¥æ ¼èæç¨çç¨åºå模åï¼P. Sewell çï¼ 2010
- ARM å POWER 宽æ¾å 忍¡åçå ¥é¨æç¨ï¼ P. Sewell ç ï¼ 2012
- MESIF ï¼ç¹å¯¹ç¹äºèç两跳ç¼åä¸è´æ§åè®®ï¼ J.R. Goodman, H.H.J. Hum ï¼ 2009