
ååã®èšäºã§ã¯ãä»®æ³çã§ã¯ãããŸãããããã»ããµã®å
éšã調ã¹ãŸããã 䞊åã³ãŒããæ£ããå®è¡ãããããã«ã¯ãå
éšã®èªã¿åã/æžã蟌ã¿ã®æé©åãå®è¡ã§ããå¶éãããã»ããµã«äŒããå¿
èŠãããããšãããããŸããã ãããã®ãã³ãã¯èšæ¶ã®éå£ã§ãã ã¡ã¢ãªããªã¢ã«ãããã¡ã¢ãªã¢ã¯ã»ã¹ïŒããæ£ç¢ºã«ã¯ããã£ãã·ã¥ãžã®ã¢ã¯ã»ã¹-ããã»ããµã¯ãã£ãã·ã¥ãä»ããŠã®ã¿å€éšãšããåãããŸãïŒãåçåã§ããŸãã ãã®ãããªé åºã®ãé倧床ãã¯ç°ãªãå ŽåããããŸããåã¢ãŒããã¯ãã£ã¯ããéžæãéå£ã®ã»ããå
šäœãæäŸã§ããŸãã ç¹å®ã®ã¡ã¢ãªããªã¢ã䜿çšããŠãããŸããŸãªã¡ã¢ãªã¢ãã«ãæ§ç¯ã§ããŸããããã¯ãããã°ã©ã ã«å®è£
ãããäžé£ã®ä¿èšŒã§ãã
ãã®èšäºã§ã¯ãC ++ 11ã¡ã¢ãªã¢ãã«ã«ã€ããŠèª¬æããŸãã
æŽå²çããã¬ãã¥ãŒåœåãã¡ãŒã«ãŒã¯ããã»ããµã®ã¡ã¢ãªã¢ãã«ã®ãªãŒãã³ãªä»æ§ãå
¬éããŠããŸããã§ãããã€ãŸãã匱ãé åºä»ããããããã»ããµãã¡ã¢ãªãæäœããããã®äžé£ã®ã«ãŒã«ãå
¬éããŠããªãã£ããããå°æ¥ã®æäœã®ããã®ã¹ããŒã¹ãç²åŸããããšãæåŸ
ããŠããŸãïŒå®éãããã€ãã®çŸ©åã¯ïŒïŒãããããã®åŸãã¡ãŒã«ãŒã¯ããã«ããéç¥ãè§£æŸããŸãã-ã®ã¬ãã«ãã¯å€©äºã«ãããã¡ãŒã«ãŒã¯ã©ãã§ããã«ãã³ã¢ãå°å
¥ãå§ããŸããã ãã®çµæãå®éã®ãã«ãã¹ã¬ããåã¯å€§è¡ã«è¡ããŸããã ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®éçºè
ã¯ãæåã«èŠåãçºããŸãããã«ãŒãã«ã§ãã«ãã³ã¢ããµããŒãããå¿
èŠãããã匱ãé åºä»ããããã¢ãŒããã¯ãã£ã®ä»æ§ã¯ãããŸããã ãã®åŸãèšèªæšæºåå£äœã¯èªããåŒãäžããŸããïŒããã°ã©ã ã¯ãŸããŸã䞊ååãããèšèªã¡ã¢ãªã¢ãã«ãæšæºåããç«¶äºåã®ãããã«ãã¹ã¬ããå®è¡ãä¿èšŒããæãæ¥ãŸãããããã»ããµã¡ã¢ãªã¢ãã«ã®ä»æ§ã¯ãããŸããã§ããã ãã®çµæã仿¥ã®ã»ãšãã©ãã¹ãŠã®ææ°ã®ããã»ããµã¢ãŒããã¯ãã£ã¯ãã¡ã¢ãªã¢ãã«ã®ãªãŒãã³ãªä»æ§ãåããŠãããJavaã.NETãC ++ã¡ã¢ãªã¢ãã«ã®æšæºã§ã®äœæ¥ã¯ããã®ãããªä»æ§ã®åºçŸã«å€§ããªåœ¹å²ãæãããŸããã
C ++ã¯ãäœã¬ãã«ã®ãã®ãé«ã¬ãã«ã§è¡šçŸããèœåã§é·ãéæåã§ãã C ++ 11ã¡ã¢ãªã¢ãã«ãéçºãããšããã¿ã¹ã¯ã¯ãã®ããããã£ã«éåããããšã§ã¯ãããŸããã§ãããã€ãŸããããã°ã©ãã«æå€§éã®æè»æ§ãäžããããšã§ããã ä»ã®èšèªïŒäž»ã«JavaïŒã®æ¢åã®ã¡ã¢ãªã¢ãã«ãšåæããªããã£ããšããã¯ããªãŒã¢ã«ãŽãªãºã ã®å
éšæ§é ã®å
žåçãªäŸãåæããåŸãæšæºã®éçºè
ã¯1ã€ã§ã¯ãªã
3ã€ã®ã¡ã¢ãªã¢ãã«ãææ¡ããŸããã
- é æ¬¡äžè²«æ§
- ã»ãã³ãã£ã¯ã¹ã®ååŸ/è§£æŸ
- ç·©åãããã¡ã¢ãªã®é åºä»ã
ãããã®ã¡ã¢ãªã¢ãã«ã¯ãã¹ãŠãC ++ã§1ã€ã®åæ
std::memory_order
ã§å®çŸ©ãããæ¬¡ã®6ã€ã®å®æ°ããããŸãã
memory_order_seq_cst
é æ¬¡æŽåã¢ãã«ãæããŸãmemory_order_acquire
ã memory_order_release
ã memory_order_acq_rel
ã memory_order_consume
ç²åŸ/è§£æŸã®ã»ãã³ãã£ã¯ã¹ã«åºã¥ããŠã¢ãã«ãåç
§ããŸãmemory_order_relaxed
ãªã©ãã¯ã¹ããã¢ãã«ã瀺ããŸã
ãããã®ã¢ãã«ãæ€èšããåã«ãããã°ã©ã ã§ã¡ã¢ãªã¢ãã«ãæå®ããæ¹æ³ã決å®ããå¿
èŠããããŸãã ããã§åã³ã¢ãããã¯æäœã«æ»ãå¿
èŠããããŸãã
æšæºã®
memory_order
æšæºã®ã¢ãããã¯æäœãžã®åŒæ°ãšããŠæå®ãããŠããããã
ã¢ãããã¯æ§ã«é¢ããèšäºã§åŒçšããæäœã¯ã
memory_order
C ++ 11ã§å®çŸ©ãããŠããæäœãšã¯é¢ä¿ãããŸããã ããã«ã¯2ã€ã®çç±ããããŸãã
- ã»ãã³ãã£ãã¯ïŒå®éãæãŸããé åºïŒã¡ã¢ãªããªã¢ïŒã¯ãå®è¡ããã¢ãããã¯æäœãå
·äœçã«æããŸãã èªã¿åã/æžã蟌ã¿ã¢ãããŒãã§ã®ããªã¢ã®é
眮ã¯ãããªã¢èªäœãååšããã³ãŒãã«æå³çã«ãŸã£ããé¢ä¿ããŠããªããããã·ã£ãŒãããºã ã§ããããã¯ãåçã®ãã®ã®äžã®åãªãåœä»€ã§ãã ããã«ãèªã¿åã/æžã蟌ã¿ããªã¢ã¯ã¢ãŒããã¯ãã£ã«å€§ããäŸåããŠããŸãã
- å®çšçïŒIntel Itaniumã«ã¯ãä»ã®ã¢ãŒããã¯ãã£ãšã¯ç°ãªããèªã¿åã/ã¡ã¢ãªåœä»€ããã³RMWæäœã®ã¡ã¢ãªé åºãæå®ããç¹å¥ãªæ¹æ³ããããŸãã Itaniumã§ã¯ãé åºä»ãã®ã¿ã€ãã¯ãåœä»€èªäœã®ãªãã·ã§ã³ã®ãã©ã°ïŒååŸãè§£æŸããŸãã¯ãªã©ãã¯ã¹ïŒãšããŠç€ºãããŸãã ããã«ãã¢ãŒããã¯ãã£ã«ç²åŸ/è§£æŸã»ãã³ãã£ã¯ã¹ãæå®ããããã®åå¥ã®åœä»€ïŒã¡ã¢ãªããªã¢ïŒã¯ãããŸããã
atomic<T>
æäœãå®éã«ã©ã®ããã«èŠãããã瀺ããŸã
std::atomic<T>
ã¯ã©ã¹ã®ãã¹ãŠã®ç¹æ®åã«ã¯ãå°ãªããšã以äžã®ã¡ãœãããå¿
èŠã§ãã
void store(T, memory_order = memory_order_seq_cst); T load(memory_order = memory_order_seq_cst) const; T exchange(T, memory_order = memory_order_seq_cst); bool compare_exchange_weak(T&, T, memory_order = memory_order_seq_cst); bool compare_exchange_strong(T&, T, memory_order = memory_order_seq_cst);
åå¥ã®ã¡ã¢ãªããªã¢ãã¡ãããC ++ 11ã«ã¯åå¥ã®ç©ºãã¡ã¢ãªããªã¢é¢æ°ããããŸãã
void atomic_thread_fence(memory_order); void atomic_signal_fence(memory_order);
å®éã
atomic_thread_fence
䜿çšãããšã
atomic_thread_fence
èªã¿åã/æžã蟌ã¿ããªã¢ã®ã¢ãããŒãã䜿çšã§ããŸãããããã¯å»æ¢ããããšèŠãªãããŸãã ãã ãã
memory_order
é åºä»ãã¡ãœããèªäœ
memory_order
ãèªã¿åãããªã¢ïŒLoad / LoadïŒãŸãã¯æžã蟌ã¿ããªã¢ïŒStore / StoreïŒãæå®ããæ¹æ³ãæäŸã
memory_order
ãã
atomic_signal_fence
ãã·ã°ãã«ãã³ãã©ã§ã®äœ¿çšãç®çãšããŠããŸãã ååãšããŠããã®é¢æ°ã¯ã³ãŒããçæããŸããããã³ã³ãã€ã©ãŒã®éå£ã§ãã
ã芧ã®ãšãããC ++ 11ã®ããã©ã«ãã®ã¡ã¢ãªã¢ãã«ã¯é 次äžè²«æ§ã§ãã æåã«æ€èšããŸãã ããããæåã«ãã³ã³ãã€ã©ãŒã®éå£ã«ã€ããŠå°ã説æããŸãã
ã³ã³ãã€ã©ãŒã®éå£
誰ãç§ãã¡ãæžããã³ãŒããäžŠã¹æ¿ããããšãã§ããŸããïŒ ããã»ããµããããå®è¡ã§ããããšãããããŸããã ããããäžŠã¹æ¿ãã®å¥ã®ãœãŒã¹-ã³ã³ãã€ã©ããããŸãã
æé©åïŒç¹ã«ã°ããŒãã«ïŒããã³ãã¥ãŒãªã¹ãã£ãã¯ã®å€ãã®æ¹æ³ããã·ã³ã°ã«ã¹ã¬ããå®è¡ã®ä»®å®ïŒããããæé»çïŒã®äžã§éçºãããŸããïŒãããŠãŸã éçºäžã§ãïŒã ã³ãŒãããã«ãã¹ã¬ããã§ããããšãã³ã³ãã€ã©ãŒãçè§£ããã®ã¯ããªãé£ããïŒããããçè«çã«ã¯äžå¯èœã§ãïŒã ãããã£ãŠãã³ã³ãã€ã©ã«ã¯ãã³ããå¿
èŠã§ã-éå£ã ãã®ãããªããªã¢ã¯ã³ã³ãã€ã©ã«äŒããŸããããªã¢ã®
åã®ã³ãŒããããªã¢ã®
åŸãã®ã³ãŒã
ã«ç§»åïŒæ··åïŒãããªãã§ãã ããã ã³ã³ãã€ã©ããªã¢èªäœã¯ã³ãŒããçæããŸããã
MS Visual C ++ã®å Žåãã³ã³ãã€ã©ããªã¢ã¯æ¬äŒŒé¢æ°
_ReadWriteBarrier()
ïŒãã®ååã¯åžžã«ç§ãå°æãããŸããïŒèªã¿åã/æžã蟌ã¿ã¡ã¢ãªããªã¢ãšã®å®å
šãªé¢é£ä»ã-æãéãã¡ã¢ãªããªã¢ïŒã GCCããã³Clangã®å Žåã
æŽç·Žããããã¶ã€ã³ã§ã
__asm__ __volatile__ ( "" ::: "memory" )
ã¢ã»ã³ãã©ãŒ
__asm__ __volatile__ ( ⊠)
æ¿å
¥ã¯ãäœããã®æ¹æ³ã§GCC / Clangã«å¯Ÿããéå£ã§ãããããšã«æ³šæããŠãã ããïŒã³ã³ãã€ã©ãŒã¯ãã³ãŒãå
ã§ããããã¹ããŒãŸãã¯äžäžã«ç§»åããæš©å©ãæã¡ãŸããïŒ
__volatile__
修食åã¯ãããèšããŸãïŒã
memory_order
ã¯ãããã»ããµãšåæ§ã«C ++ 11ããµããŒãããã³ã³ãã€ã©ãŒã«åœ±é¿ãäžããŸãããããã¯ã³ã³ãã€ã©ãŒã®éå£ã§ãããã³ã³ãã€ã©ãŒãã³ãŒããäžŠã¹æ¿ããïŒã€ãŸãæé©åããïŒèœåãå¶éããŸãã ãããã£ãŠããã¡ããã³ã³ãã€ã©ãæ°ããæšæºãå®å
šã«ãµããŒãããŠããªãéããç¹å¥ãªã³ã³ãã€ã©ããªã¢ãæå®ããå¿
èŠã¯ãããŸããã

ã·ãŒã±ã³ã·ã£ã«äžè²«æ§
ããã¯ããªãŒã¹ã¿ãã¯ïŒããã¯ããã¯ããªãŒããŒã¿æ§é ã®æãåçŽãªãã®ïŒãå®è£
ããã³ã³ãã€ã«ããŠãã¹ããããšããŸãã ãããŠãå¥é¢ïŒã³ã¢ãã¡ã€ã«ïŒãååŸããŸãã å
æ°ïŒ ããã¯ããªãŒã¹ã¿ãã¯ãè¡ããšã«å®è£
ãããã«ãã¹ã¬ããããšãã¥ã¬ãŒãããŠãã¹ããªãŒã 1ã®è¡Kãšã¹ããªãŒã 2ã®è¡Nãåæã«å®è¡ããèŽåœçãªçµã¿åããã«çåãæãããããšã©ãŒãæ¢ãå§ããŸãïŒãããã¬ãŒã¯ããã§ã¯åœ¹ã«ç«ã¡ãŸããïŒã厩å£ã ããã€ãã®ãšã©ãŒãèŠã€ããŠä¿®æ£ãããããããŸãããããšã«ãã-ããã¯ããªãŒã®ã¹ã¿ãã¯ã¯èœã¡ãŸãã ãªãã§ïŒ
ãšã©ãŒãèŠã€ããŠãåæã«å®è¡ãããŠããã¹ã¬ããã«ã€ããŠããã°ã©ã ã®è¡ãæ¯èŒããããšã詊ã¿ãããšã¯ã
é æ¬¡äžè²«æ§ä¿èšŒãšåŒã°ããŸãã ããã¯å³å¯ãªã¡ã¢ãªã¢ãã«ã§ãããããã»ããµãããã°ã©ã ã§èšè¿°ããã
é åºã§ãã¹ãŠãæ£ç¢ºã«å®è¡ããããšãåæãšããŠããŸãã ããšãã°ã次ã®ãããªã³ãŒãã®å ŽåïŒ
é æ¬¡äžè²«æ§ã«æå¹ãªã®ã¯ã
a.store / b.load
ãš
x.load / y.store
ã亀æããã¹ã¯ãªãããé€ãããã¹ãŠã®å®è¡ã¹ã¯ãªãã
x.load / y.store
ã ãã®ã³ãŒãã§ã¯ãload / storeã§
memory_order
åŒæ°ãæç€ºçã«
memory_order
ããªãããšã«æ³šæããŠãã ãããããã©ã«ãã®åŒæ°å€ã«äŸåããŠããŸãã
ã³ã³ãã€ã©ãŒã«ã¯ãŸã£ããåãä¿èšŒãé©çšãããŸãïŒã³ã³ãã€ã©ãŒã¯
ã memory_order_seq_cst
åŸã® memory_order_seq_cst
ããã®ããªã¢ã®äžã«ç§»åããããã«ã³ãŒããäžŠã¹æ¿ããããšã¯çŠããããŠããããã®éãåæ§ã§ã-seq_cst-barrierã®
åã®æäœã¯ããªã¢ã®äžã§çç¥ã§ããŸããã
ã·ãŒã±ã³ã·ã£ã«æŽåæ§ã¢ãã«ã¯çŽæçã«äººéã«è¿ããã®ã§ãããéåžžã«éå€§ãªæ¬ ç¹ããããŸããããã¯ãææ°ã®ããã»ããµã«ã¯å³å¯ããããšããããšã§ãã ããã»ããµãææ©çå®è¡ãå®å
šã«äœ¿çšããããšãèš±å¯ããªããæãå³ããã¡ã¢ãªããªã¢ã«ã€ãªãããŸãã ãã®ãããæ°ããC ++æšæºã§ã¯ãã®ãããªåŠ¥åæ¡ãæ¡çšãããŸããã
- é æ¬¡äžè²«æ§ã¢ãã«ã¯ãå³å¯ããšæç¢ºãã®ããã«ãã¢ãããã¯æäœã®ããã©ã«ãã¢ãã«ãšããŠäœ¿çšããå¿
èŠããããŸãã
- ä»ã®ãã匱ãã¡ã¢ãªã¢ãã«ãC ++ã«å°å
¥ããŠãææ°ã®ã¢ãŒããã¯ãã£ã®å¯èœæ§ãå®çŸãã
é æ¬¡äžè²«æ§ã«å ããŠãååŸ/è§£æŸã»ãã³ãã£ã¯ã¹ã«åºã¥ãã¢ãã«ãææ¡ãããŸããã

ã»ãã³ãã£ã¯ã¹ã®ååŸ/è§£æŸ
ååã®ååŸ-ãªãªãŒã¹ã®ã»ãã³ãã£ã¯ã¹ããããã®ã»ãã³ãã£ã¯ã¹ã¯ãªãœãŒã¹ã®ååŸïŒååŸïŒããã³ãªãªãŒã¹ïŒãªãªãŒã¹ïŒã«äœããã®é¢ä¿ããããšçµè«ä»ããããšãã§ããŸãã 確ãã«ããã§ãã ãªãœãŒã¹ããã£ããã£ãããšãã¡ã¢ãªããã¬ãžã¹ã¿ã«èªã¿èŸŒãŸããè§£æŸãããšã¬ãžã¹ã¿ããã¡ã¢ãªã«æžã蟌ãŸããŸãã
load memory, register ; membar #LoadLoad | #LoadStore ;
ã芧ã®ãšããããã®ã³ãŒãã§ã¯ãéãéå£
#StoreLoad
ã ãŸããacquire-barrierãšrelease-barrierã¯ã©ã¡ããã»ãããªã¢ã§ããããšã«æ°ä»ãããšãã§ããŸã
ãacquireã¯åŸç¶ã®ããŒã/ã¹ãã¢ã§ä»¥åã®ã¹ãã¢æäœãé åºä»ããããreleaseã¯åŸç¶ã®ããŒã/ã¹ãã¢ã§ä»¥åã®ããŒããé åºä»ãããŸããã ã ããã¯ãããã»ããµãšã³ã³ãã€ã©ã®äž¡æ¹ã«é©çšãããŸãã
ååŸ/ãªãªãŒã¹ã¯
ãååŸ/ãªãªãŒã¹
éã«å²ãŸãããã¹ãŠã®ã³ãŒãã«å¯Ÿããéå£ã§ãã ç²åŸããªã¢ããªãŒã¯ãã
åã®äžéšã®æäœïŒããã»ããµãŸãã¯ã³ã³ãã€ã©ã«ãã£ãŠäžŠã¹æ¿ãå¯èœïŒãç²åŸ/ãªãªãŒã¹ã»ã¯ã·ã§ã³å
ã«ãã
ããªãªãŒã¹ããªã¢ãäžã«ç§»åãã
åŸã®äžéšã®æäœãïŒåã³ããã»ããµãŸãã¯ã³ã³ãã€ã©ã«ãã£ãŠïŒç²åŸ/ãªãªãŒã¹å
ã«ããå ŽåããããŸãã»ã¯ã·ã§ã³ã ãã ããacquire-releaseå
ã§å®äºããæäœã¯ãããè¶
ããããšã¯ãããŸããã
ãããããååŸ/è§£æŸã»ãã³ãã£ã¯ã¹ãé©çšããæãåçŽãªäŸã¯ã¹ãã³ããã¯ã§ãã
ããã¯ããªãŒããã³ã¹ãã³ããã¯ããã¯ããªãŒã¢ã«ãŽãªãºã ã«é¢ãããµã€ã¯ã«ã®èšäºã§ãããã¯ã¢ã«ãŽãªãºã ã®äŸãæããŠããã®ã¯å¥åŠã«æãããããããŸããã 説æããå¿
èŠããããŸãã
ãããã«ããŠããç§ã¯çŽç²ãªããã¯ããªãŒã®ç±çãªãã¡ã³ã§ã¯ãããŸããã ã¯ããå®å
šãªããã¯ããªãŒïŒããã«åŸ
æ©ããªãŒïŒã¢ã«ãŽãªãºã ã¯ç§ã幞ãã«ããå®è£
ãããããšãããã£ãå Žåã¯äºéã«å¹žãã«ãªããŸãïŒããã¯åžžã«èµ·ãããšã¯éããŸããïŒã ç§ã¯å®çšçãªã¢ãããŒããæ¯æããŠããŸãã广çãªãã®ã¯ãã¹ãŠè¯ãã§ãã ãããã£ãŠãç§ã¯ãå©çãããããããšãã§ããããã¯ãé©çšããããšã軜disããŸããã ã¹ãã³ããã¯ã¯ãããå°ããªã³ãŒããã€ãŸãæ°åã®ã¢ã»ã³ãã©ãŒåœä»€ããä¿è·ãããå Žåãéåžžã®ãã¥ãŒããã¯ã¹ãšæ¯èŒããŠå€§ããªå©ç¹ãæäŸã§ããŸãã ããã«ãã¹ãã³ããã¯ã¯ããã®åçŽãã«ãããããããããããçš®é¡ã®è峿·±ãæé©åã®å°œããããšã®ãªããœãŒã¹ã§ãã
ããã¯ãååŸ/è§£æŸæã«æãåçŽãªã¹ãã³ããã¯ã®ããã«èŠããŸãïŒC ++ã®å°éå®¶ã¯ãç¹æ®ãªã¿ã€ãã®
atomic_flag
ã䜿çšããŠã¹ãã³ããã¯ãå®è£
ããå¿
èŠãããããšãææããŸãããã¢ãããã¯å€æ°ïŒããŒã«å€ã§ã¯ãªãïŒã«ã¹ãã³ããã¯ãæ§ç¯ããŸã-ããã®èгç¹ããã¯ããèŠèŠçã§ãèšäºïŒïŒ
class spin_lock { atomic<unsigned int> m_spin ; public: spin_lock(): m_spin(0) {} ~spin_lock() { assert( m_spin.load(memory_order_relaxed) == 0);} void lock() { unsigned int nCur; do { nCur = 0; } while ( !m_spin.compare_exchange_weak( nCur, 1, memory_order_acquire )); } void unlock() { m_spin.store( 0, memory_order_release ); } };
ãã®ã³ãŒãã§ã¯ã
compare_exchange
ãåç
§ã«ãã£ãŠãã®æåã®åŒæ°ãåãå
¥ããCASã倱æããå Žåã«ããã倿Žãããšããäºå®ã¯ãæ¬åœã«ç§ãæ©ãŸãããšã«æ³šæããŠãã ããïŒ ç©ºã§ãªãæ¬äœã§
do-while
ã«ãŒããäœæãã
do-while
ãŸãã
lock
ããã¹ã¿ãŒãã
lock
ã¡ãœããã§ã¯ãååŸã»ãã³ãã£ã¯ã¹ã䜿çšãã
unlock
ã¡ãœããã§ã¯ãªãªãŒã¹ã»ãã³ãã£ã¯ã¹ã䜿çšããŸãïŒã¡ãªã¿ã«ãååŸ/ãªãªãŒã¹ã»ãã³ãã£ã¯ã¹ã¯ãåæããªããã£ãããæŽå²ãåããŸãããæšæºã®éçºè
ã¯ãããŸããŸãªåæããªããã£ãã®å®è£
ãæ
éã«åæããååŸ/ãªãªãŒã¹ãã¿ãŒã³ãå°ãåºããŸããã ïŒäžã§æžããããã«ããã®å Žåã«çœ®ãããéå£ã¯ã
lock()
ãš
unlock()
éã«å²ãŸããã³ãŒããæŒããããšãèš±å¯ããŸãã-ãããå¿
èŠãªãã®ã§ãïŒ ãŸãã
m_spin
倿°ã®
ååæ§ã«ããã m_spin
m_spin=1
ã§ããéãã誰ãããã¯ãååŸã§ããªãããšãä¿èšŒãããŸãã
ã¢ã«ãŽãªãºã ã§ã¯ã
compare_exchange_weak
ã
compare_exchange_weak
ãŠããããšãããããŸãã ããã¯äœã§ãã

匱ã匷åãªCAS
èŠããŠããããã«ãããã»ããµã¢ãŒããã¯ãã£ã¯2ã€ã®ã¯ã©ã¹ã®ããããã«å±ããããšãã§ããŸããããã»ããµã¯ãã¢ãããã¯ããªããã£ãCASïŒæ¯èŒãšã¹ã¯ããïŒãå®è£
ããããLL / SCãã¢ïŒããŒããªã³ã¯/ã¹ãã¢æ¡ä»¶ä»ãïŒã®ããããã§ãã LL / SCãã¢ã䜿çšãããšãã¢ãããã¯CASãå®è£
ã§ããŸãããããèªäœã¯å€ãã®çç±ã§ã¢ãããã¯ã§ã¯ãããŸããã ãããã®çç±ã®1ã€ã¯ãLL / SCå
ã§å®è¡ãããŠããã³ãŒãããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã«ãã£ãŠäžæãããå¯èœæ§ãããããšã§ãã ããšãã°ãOSãçŸåšã®ã¹ã¬ãããæ··éãããããšã決å®ããã®ã¯ãã®æç¹ã§ãã ãããã£ãŠãã¹ãã¢æ¡ä»¶ä»ãã®å ŽåãåéåŸã¯æ©èœããŸããã ã€ãŸããCASã¯
false
ãè¿ã
false
ããå®éã«ã¯ãã®
false
ã®çç±ã¯ããŒã¿ã§ã¯ãªãããµãŒãããŒãã£ã®ã€ãã³ãïŒã¹ã¬ããã®äžæïŒã«ããå¯èœæ§ããããŸãã
ãã®èæ
®äºé
ã«ãããæšæºã®éçºè
ã¯2ã€ã®
compare_exchange
ããªããã£ãïŒåŒ±ããã³åŒ·ïŒãå°å
¥ããããã«ãªããŸããã ãããã®ããªããã£ãã¯
compare_exchange_strong
compare_exchange_weak
ããã³
compare_exchange_strong
ãšåŒã°ã
compare_exchange_strong
ã 匱ãããŒãžã§ã³
ã¯å€±æãã
å¯èœæ§ããããŸããã€ãŸãã倿°ã®çŸåšã®å€ãäºæ³ãããå€ãšçããå Žåã§ã
false
è¿ã
false
ã ã€ãŸãã匱ãCASã¯CASã®ã»ãã³ãã£ã¯ã¹ã«éåããå®éã«
true
ãè¿ãå¿
èŠãããå Žåã«
false
ãè¿ã
true
ãã§ã
true
ïŒãã ãããã®éã¯ã§ããŸããïŒïŒã匷åãªCASã¯ãããè¡ããŸãããCASã®ã»ãã³ãã£ã¯ã¹ã«å³å¯ã«åŸããŸãã ãã¡ãããäœã䟡å€ããããããããŸããã
匱ãCASã䜿çšããå¿
èŠãããå Žåãšã匷åãªCASã䜿çšããå Žå ç§ã¯ãã®ã«ãŒã«ãæãä»ããŸããïŒCASãã«ãŒãã§äœ¿çšããïŒãããCASã䜿çšããããã®äž»ãªãã¿ãŒã³ã§ããïŒãã«ãŒãå
ã«æäœããªãå ŽåïŒã€ãŸããã«ãŒãã®æ¬äœã軜ãå ŽåïŒã
compare_exchange_weak
-weak CASã䜿çšããŸãã ãã以å€ã®å Žåã匷ã
compare_exchange_strong
ã
ç²åŸ/è§£æŸã»ãã³ãã£ã¯ã¹ã®ã¡ã¢ãªé åº
äžã§è¿°ã¹ãããã«ã次ã®
memory_order
å€ã¯ãååŸ/è§£æŸã»ãã³ãã£ã¯ã¹ã®ããã«å®çŸ©ãããŠããŸãã
memory_order_acquire
memory_order_consume
memory_order_release
memory_order_acq_rel
èªã¿èŸŒã¿ïŒããŒãïŒã®å Žåãæå¹ãªå€ã¯
memory_order_acquire
ããã³
memory_order_consume
ã§ãã
æžã蟌ã¿çšïŒã¹ãã¢ïŒ
memory_order_release
ã®ã¿ã
Memory_order_acq_rel
ã¯RMWæäœ
fetch_xxx
ã
exchange
ã
fetch_xxx
ã«å¯ŸããŠã®ã¿æå¹ã§ãã äžè¬ã«ãã¢ãããã¯RMWããªããã£ãã¯ã
memory_order_acquire
ååŸã»ãã³ãã£ã¯ã¹ã
memory_order_acquire
ãªãªãŒã¹ã»ãã³ãã£ã¯ã¹
memory_order_release
ãŸãã¯ãã®äž¡æ¹ã§ãã
memory_order_acq_rel
ãæã€ããšãã§ããŸãã RMWæäœã®å Žåãread-modify-writeããªããã£ããã¢ãããã¯ãªèªã¿åããšæžã蟌ã¿ãåæã«å®è¡ããããããããã®å®æ°ã
ã»ãã³ãã£ã¯ã¹ã決å®ããŸãã æå³çã«ã¯ãRMWæäœã¯ãååŸã®èªã¿åãããªãªãŒã¹ã®ã¬ã³ãŒãããŸãã¯ãã®äž¡æ¹ãšèŠãªãããšãã§ããŸãã
RMWæäœã®ã»ãã³ãã£ã¯ã¹ã¯ãé©çšãããã¢ã«ãŽãªãºã ã§ã®ã¿æ±ºå®ã§ããŸãã å€ãã®å Žåãããã¯ããªãŒã¢ã«ãŽãªãºã ã§ã¯ãã¹ãã³ããã¯ã«å€å°äŒŒãŠããéšåãåºå¥ã§ããŸããæåã«ç¹å®ã®ãªãœãŒã¹ãååŸïŒååŸïŒããäœããå®è¡ïŒéåžžã¯æ°ããå€ãèšç®ïŒããæåŸã«ãªãœãŒã¹ã«æ°ããå€ãèšå®ïŒè§£æŸïŒããŸãã ãªãœãŒã¹ã®ååŸãRMWæäœïŒéåžžã¯CASïŒã«ãã£ãŠå®è¡ãããå Žåããã®ãããªæäœã¯ã»ãã³ãã£ã¯ã¹ãååŸããå¯èœæ§ããããŸãã æ°ããå€ã®èšå®ãRMWããªããã£ãïŒCASãŸãã¯
exchange
ïŒã«ãã£ãŠå®è¡ãããå Žåãã»ãšãã©ã®å ŽåããªãªãŒã¹ã»ãã³ãã£ã¯ã¹ããããŸãã ãããªãå¯èœæ§ãé«ãããšããçç±ãæ¿å
¥ãããŠããŸããRMWæäœã«é©ããã»ãã³ãã£ã¯ã¹ãçè§£ããã«ã¯ãã¢ã«ãŽãªãºã ã®è©³çްãªåæãå¿
èŠã§ãã
RMWããªããã£ããåå¥ã«å®è¡ãããå ŽåïŒååŸ/è§£æŸãã¿ãŒã³ãåé¢ããããšã¯äžå¯èœã§ãïŒãã»ãã³ãã£ã¯ã¹ã®3ã€ã®ãªãã·ã§ã³ãå¯èœã§ãã
memory_order_seq_cst
-RMWæäœã¯ã¢ã«ãŽãªãºã ã®éèŠãªèŠçŽ ã§ããã³ãŒããäžŠã¹æ¿ããèªã¿åããšæžã蟌ã¿ãäžäžã«ç§»åãããšãšã©ãŒãçºçããå¯èœæ§ããããŸãmemory_order_acq_rel
- memory_order_seq_cst
ã«äŒŒãŠãmemory_order_seq_cst
ããRMWæäœã¯ååŸ/è§£æŸã»ã¯ã·ã§ã³å
ã«ãããŸãmemory_order_relaxed
-RMWæäœïŒãã®ããŒãéšåãšã¹ãã¢éšåïŒãã³ãŒãã®äžäžã«ç§»åããŠãïŒããšãã°ãæäœããã®ãããªã»ã¯ã·ã§ã³å
ã«ããå ŽåãååŸ/è§£æŸã»ã¯ã·ã§ã³å
ã§ïŒãšã©ãŒã«ãªããŸãã
ãããã®ãã¹ãŠã®ãã³ãã¯ãRMWããªããã£ãã«1ã€ãŸãã¯å¥ã®ã»ãã³ãã£ã¯ã¹ãæããããã®ããã€ãã®äžè¬ååãæŠèª¬ãã詊ã¿ãšããŠã®ã¿ãšãã¹ãã§ãã åã¢ã«ãŽãªãºã ã«ã€ããŠè©³çްãªåæãå®è¡ããå¿
èŠããããŸãã
ã»ãã³ãã£ã¯ã¹ãæ¶è²»ãã
åå¥ã®ããã匱ããååŸã»ãã³ãã£ã¯ã¹ã®çš®é¡ããããŸã-æ¶è²»èªã¿åãã»ãã³ãã£ã¯ã¹ã§ãã ãã®ã»ãã³ãã£ã¯ã¹ã¯ãDEC Alphaããã»ããµã®ãè³èŸããšããŠå°å
¥ãããŸããã
ã¢ã«ãã¡ã¢ãŒããã¯ãã£ã«ã¯ãä»ã®ææ°ã®ã¢ãŒããã¯ãã£ãšã¯å€§ããªéãããããŸããããŒã¿ã®äŸåé¢ä¿ãå£ãå¯èœæ§ããããŸãã ãã®ã³ãŒãäŸã§ã¯ïŒ
struct foo { int x; int y; } ; atomic<foo *> pFoo ; foo * p = pFoo.load( memory_order_relaxed ); int x = p->x;
圌女ã¯ã
p->x
èªã¿ãäžŠã¹æ¿ããŠãå®éã«
p
ååŸã§ããŸãïŒãããã©ã®ããã«å¯èœããèããªãã§ãã ãã-ãã
㯠Alpha
ããããã£ã§ããAlphaãæäœããå¿
èŠããªãããã確èªãæåŠãã§ããŸããïŒã
ãã®äžŠã¹æ¿ããé²ãããã«ãæ¶è²»ã»ãã³ãã£ã¯ã¹ãå°å
¥ãããŸããã æ§é äœãžã®ãã€ã³ã¿ã®ã¢ãããã¯ãªèªã¿åãã«é©çšã§ãããã®åŸã«æ§é äœã®ãã£ãŒã«ããèªã¿åããŸãã ãã®äŸã§ã¯ã
pFoo
ãã€ã³ã¿ãŒã¯æ¬¡ã®ããã«ãªããŸãã
foo * p = pFoo.load( memory_order_consume ); int x = p->x;
ã»ãã³ãã£ã¯ã¹ã¯ãèªã¿åãã®ãªã©ãã¯ã¹ããã»ãã³ãã£ã¯ã¹ãšç²åŸããã»ãã³ãã£ã¯ã¹ã®äžéã«ãããŸãã å€ãã®çŸä»£å»ºç¯ã§ã¯ããªã©ãã¯ã¹ããèªæžã«å¯Ÿå¿ããŠããŸãã
ãããŠåã³CASã«ã€ããŠ
äžèšã§ã¯ã2ã€ã®CASã䜿çšãã
atomic<T>
ã€ã³ã¿ãŒãã§ãŒã¹ã瀺ããŸãã-匱ããã®ãšåŒ·ããã®ã§ãã å®éãCASã«ã¯ããã«2ã€ã®ããªã¢ã³ããããã远å ã®åŒæ°
memory_order
ãŸãã
bool compare_exchange_weak(T&, T, memory_order successOrder, memory_order failedOrder ); bool compare_exchange_strong(T&, T, memory_order successOrder, memory_order failedOrder );
ãã®åŒæ°
failedOrder
ãšã¯äœã§ããïŒ
CASã¯èªã¿åã-倿Ž-æžã蟌ã¿ããªããã£ãã§ããããšãæãåºããŠãã ããã é害ãçºçããå Žåã§ããã¢ãããã¯èªã¿åããå®è¡ããŸãã
failedOrder
åŒæ°ã¯ãCASã倱æããå Žåã®ãã®èªã¿åãã®ã»ãã³ãã£ã¯ã¹ãå®çŸ©ããã ãã§ãã éåžžã®èªã¿åããšåãå€ããµããŒããããŠããŸãã
å®éã«ã¯ãã倱ææã®ã»ãã³ãã£ã¯ã¹ãã®è¡šç€ºã¯ã»ãšãã©å¿
èŠãããŸããã ãã¡ããããã¹ãŠã¢ã«ãŽãªãºã ã«äŸåããŠããŸãïŒ
ç·©åãããã»ãã³ãã£ã¯ã¹
æåŸã«ã3çªç®ã®ã¿ã€ãã®ã¢ãããã¯æäœã¢ãã«ã¯ç·©åãããã»ãã³ãã£ã¯ã¹ã§ãããããã¯ãã¹ãŠã®ã¢ãããã¯ããªããã£ãïŒããŒããã¹ãã¢ããã¹ãŠã®RMWïŒã«é©çšå¯èœã§ããã
ã»ãšãã©å¶éã課ããªããããããã»ããµãŒã¯
ã»ãŒå®å
šã«äžŠã¹æ¿ããããšãã§ãããã®ãã«ãã¯ãŒãçºæ®ããŸãã ãªãã»ãšãã©ïŒ
ãŸããæšæºã®èŠä»¶ã¯ããªã©ãã¯ã¹ããæäœã®
ååæ§ã芳å¯ããããšã§ãã ã€ãŸãããªã©ãã¯ã¹ããæäœã§ãããéšåçãªå¹æã䌎ããã«åå²ã§ããªãã¯ãã§ãã
第äºã«ãææ©çé²é³ã¯ã¢ãããã¯ãªã©ãã¯ã¹é²é³ã®æšæºã§ã¯çŠæ¢ãããŠããŸãã
ãããã®èŠä»¶ã¯ãããã€ãã®åŒ±ãé åºä»ããããã¢ãŒããã¯ãã£ã§ã®ã¢ãããã¯ãªç·©åæäœã®å®è£
ã«å¶éã課ãå ŽåããããŸãã ããšãã°ãIntel Itaniumã®ã¢ãããã¯å€æ°ã®ç·©åãããããŒãã¯ã
load.acq
ãšããŠå®è£
ãã
load.acq
ïŒèªã¿åããååŸããŸã
load.acq
ååŸãšC ++ã®ååŸãæ··åããªãã§ãã ããïŒã
Itaniumã®ã¬ã¯ã€ãšã ç§ã®èšäºã§ã¯ãIntel Itaniumã«ã€ããŠããèšåããŠããŸãã ããªãã¯ãç§ãItaniumã¢ãŒããã¯ãã£ã®ãã¡ã³ã§ãããšããå°è±¡ãåŸããããããŸããã ããããç§ã¯ãã¡ã³ã§ã¯ãããŸããã...
Itanium VLIWã¢ãŒããã¯ãã£ã¯ãã³ãã³ãã·ã¹ãã ã®æ§ç¯åçãä»ã®ã¢ãŒããã¯ãã£ãšã¯å€å°ç°ãªããŸãã ã¡ã¢ãªã®é åºã¯ãããŒã/ã¹ãã¢/ RMWåœä»€ã®æ¥å°ŸèŸãšããŠç€ºãããŸãããããã¯ä»ã®ææ°ã®ã¢ãŒããã¯ãã£ã«ã¯åœãŠã¯ãŸããŸããã 䜿çšãååŸããªãªãŒã¹ãªã©ã®çšèªã§ãããC ++ 11ãItaniumãã廿¢ãããŠããªãããšã瀺åããŠããŸãã
話ãæãåºããšãItaniumã¯ãAMDãæéå
ã«å€§éšãããã64ãããx86æ¡åŒµæ©èœã§ããAMD64ããªãªãŒã¹ããªãã£ãå Žåã«ç§ãã¡å
šå¡ã座ã£ãŠããã¢ãŒããã¯ãã£ïŒãŸãã¯ãã®åå«ïŒã§ãã åœæã®ã€ã³ãã«ã¯ã64ãããã³ã³ãã¥ãŒãã£ã³ã°çšã®æ°ããã¢ãŒããã¯ãã£ãåŸã
ã«éçºããŠããŸããã ãããŠããã®æ°ããã¢ãŒããã¯ãã£ã«ã€ããŠæŒ ç¶ãšã»ã®ããããã ãã³ãããããã¹ã¯ãããäžã®Itaniumãç§ãã¡ãåŸ
ã£ãŠããããšãçè§£ããããšãã§ããŸããã ã¡ãªã¿ã«ãMicrosoft Windowsãžã®ç§»æ€ãšItaniumçšã®Visual C ++ã³ã³ãã€ã©ãããã鿥çã«èšŒèšããŠããŸãïŒèª°ããitaniumã§WindowsãåäœããŠããã®ãèŠãããšããããŸããïŒïŒ Itaniumã¯ãµãŒããŒã»ã°ã¡ã³ãã«ãšã©ãŸããéçºã®ããã®é©åãªãªãœãŒã¹ãååŸã§ããããã£ãããšæ»ã«ãããŠããŸããã
äžæ¹ããéåžžã«é·ãåœä»€èªãïŒVLIW-éåžžã«é·ãåœä»€èªïŒã®åœä»€ã®ãæããæã€Itaniumã¯ãäŸç¶ãšããŠè峿·±ãç»æçãªããã»ããµã§ãã Itaniumã§ã¯ãææ°ã®ããã»ããµèªäœãå®è¡ãããã®-å®è¡ãŠããããããŒãããæäœãäžŠã¹æ¿ãã-ã¯ã³ã³ãã€ã©ã«å§ããããŸããã ããããã³ã³ãã€ã©ãŒã¯ãã®ãããªã¿ã¹ã¯ã«å¯ŸåŠã§ãããæé©ãªã³ãŒãã§ã¯ãªãçæïŒããã³çæïŒãè¡ãããšãã§ããŸããã§ããã ãã®çµæãItaniumã®ããã©ãŒãã³ã¹ã¯æ°åäœäžããŸããããããŠãVLIWã®ããã³ãã«ãã«é¢ããæç€ºã®äžåçãªïŒItaniumã®èгç¹ããã®ïŒé
åžã®ã¿ã«ããïŒItaniumã§äœãšåŒã°ããŠããã®ãèŠããŠããŸãããã翻蚳-ããã³ãã«ãã¯èšæ¶ãããŠããŸããïŒå®è¡ãããã¯ã®äžåçãªããŒãã
Itanium â .
, , , ?..
Happens-before, synchronized-with
, C++11, : « , , â happened before, synchronized-with ?»
â .
C++ Concurrency in Action (
), . .
â () C++, ,
. C++.
, ,
memory_order
- lock-free . sequential consistency â -
memory_order
- . , .
â acquire/release relaxed â .
UPD:
cheremin . , sequential consistency , â . : lock-free , , â
.

lock-free
â
relacy . , . , lock-free relacy ( ? â , , , ). , ,
memory_order
-, production- .
lock-free , â , . , .
( «» â , , - ) ( ), â , .
, relacy, , ( â relacy ), Intel â , (relacy - ) . . - safe iterators STL.
Google
ThreadSanitizer . data race ( ) , , , . , STL, â (Clang 3.2,
GCC 4.8 ).
ThreadSanitizer â , â .
libcds , ,
libcds .
x86x86, , (weakly-ordered) . , lock-free : , x86, .
, memory_order
- null ( nop!), â x86 . , release- â mov
, mov
relaxed-.
lock-free , , x86- - .
« ...» â
, C++11! , ,
. - :
template <typename T> class atomic { template <memory_order Order = memory_order_seq_cst> T load() const ; template <memory_order Order = memory_order_seq_cst> void store( T val ) ; template <memory_order SuccessOrder = memory_order_seq_cst> bool compare_exchange_weak( T& expected, T desired ) ;
, , .
, , . [] . , , (, , , release- ). . , :
extern std::memory_order currentOrder ; std::Atomic<unsigned int> atomicInt ; atomicInt.store( 42, currentOrder ) ;
C++11. , , , :
- , â , ?
- sequential consistent â « ».
currentOrder
, , - switch/case
currentOrder
. - . , â release- acquire-
.
memory_order
. , :
std::Atomic<int> atomicInt ; atomicInt.store<std::memory_order_release>( 42 ) ;
, , «» , â .
C++11 , , â C.
std::atomic
C++11 C-
atomic_load
,
atomic_store
.
, libcds , C++11 , . , - , libcds C++11.
â
.

« ». , - âŠ
â â â lock-free .
ããã¯ããªãŒã®ããŒã¿æ§é éå§ããåºæ¬ïŒ
äžïŒ
å€ããïŒ