ãããã®3ã€ã®èšäºã§ã¯ãã¢ãããã¯æäœãã¡ã¢ãªããªã¢ãã¹ã¬ããéã®é«éããŒã¿äº€æãããã³ãexecute-around-idiomãã®äŸã䜿çšããŠãã·ãŒã±ã³ã¹ãã€ã³ããã«ã€ããŠè©³ãã説æããåæã«äœããããããšããŸãã䟿å©-å€æ°ãŸãã¯é¢æ°ãæã€ã¡ã³ããŒãæã€ä»»æã®æäœã«å¯ŸããŠããªããžã§ã¯ããã¹ã¬ããã»ãŒãã«ããã¹ããŒããã€ã³ã¿ãŒã 次ã«ã8ã64ã³ã¢ã§é«åºŠã«æé©åãããããã¯ããªãŒã¢ã«ãŽãªãºã ã®ããã©ãŒãã³ã¹ãå®çŸããããã«ããã䜿çšããæ¹æ³ã瀺ããŸãã
é¢é£ãã3ã€ã®èšäºïŒ
- ãªããžã§ã¯ããã¹ã¬ããã»ãŒãã«ãã
- stdã®é«éå:: shared_mutexã10å
- ã¹ã¬ããã»ãŒãstd ::ããã¯ã®ãªããããããã©ãŒãã³ã¹ãåããããã
â ç§ã®è±èªã®èšäº
â 3ã€ã®èšäºãã¹ãŠã®äŸãšãã¹ã
æšæºC ++ã©ã€ãã©ãªã«ã¯ãè¿œå ã®ããã¯ãªãã§è€æ°ã®ã¹ã¬ããã§äœ¿çšã§ããã¹ã¬ããã»ãŒãã³ã³ããïŒé åããªã¹ããããããªã©ïŒã¯ãããŸããã ãã«ãã¹ã¬ãã亀æã®æšæºã³ã³ããã䜿çšãããšãã³ãŒãã»ã¯ã·ã§ã³ã®1ã€ããã¥ãŒããã¯ã¹ã§ä¿è·ããã®ãå¿ãããã誀ã£ãŠå¥ã®ãã¥ãŒããã¯ã¹ã§ä¿è·ããã®ãå¿ãããããå±éºããããŸãã
æããã«ãéçºè ã¯æšæºçãªãœãªã¥ãŒã·ã§ã³ã®ä»£ããã«ç¬èªã®ãœãªã¥ãŒã·ã§ã³ã䜿çšãããšãããå€ãã®ééããç¯ããŸãã ã¿ã¹ã¯ãéåžžã«è€éã§ãæšæºã«è§£æ±ºçããªãå Žåãããã解決ããéçºè ã¯ãšã©ãŒã«errorsããŸãã
ãå®çšæ§ã¯éã®æã¡ã©ããã®ãªãããšãããéèŠãïŒãå®çšæ§ã¯çŽåºŠãããåªããŠãããïŒã®ååã«åºã¥ããŠããã®åé¡ã«å¯Ÿããçæ³çã§ã¯ãªãå®çšçãªè§£æ±ºçãäœæããããšããŸãã
ãã®èšäºã§ã¯ããªããžã§ã¯ããã¹ã¬ããã»ãŒãã«ããã¹ããŒããã€ã³ã¿ãŒãå®è£ ããŸããããã©ãŒãã³ã¹ã¯ãæé©åãããããã¯ããªãŒã³ã³ãããŒã«å£ããŸããã
ãã®ãããªãã€ã³ã¿ãŒã䜿çšããåçŽåãããæé©åãããŠããªãäŸïŒ
int main() { contfree_safe_ptr< std::map<std::string, int> > safe_map_string_int; std::thread t1([&]() { safe_map_string_int->emplace("apple", 1); }); std::thread t2([&]() { safe_map_string_int->emplace("potato", 2); }); t1.join(); t2.join(); std::cout << "apple = " << (*safe_map_string_int)["apple"] << ", potato = " << (*safe_map_string_int)["potato"] << std::endl; return 0; }
ã¢ã«ãŽãªãºã ã®åã¹ãããã§ãå¿ èŠãªåäœãä¿èšŒããæšæºããåŒçšç¬Šãä»ããŸãã
C ++ã¡ã¢ãªã¢ãã«ãã¹ã¬ããéã§ããŒã¿ãåæããã³äº€æããããã®ããŸããŸãªå¯èœãªãªãã·ã§ã³ã«ã€ããŠè©³ãã調ã¹ãŸãã
2çªç®ã®èšäºã§ã¯ãæé©åãããã競åã®ãªãå ±æãã¥ãŒããã¯ã¹ããšããã«åºã¥ããæé©åããããã€ã³ã¿ãŒcontfree_safe_ptr <>ãå®è£ ããŸãã 3çªç®ã®èšäºã§ã¯ãcontfree_safe_ptr <>ã®æé©ãªäœ¿çšäŸã瀺ããããã©ãŒãã³ã¹ãã¹ããè¡ããŸãã
éå§ãã
ãŸããsafe_ptr <T>ã¹ããŒããã€ã³ã¿ãŒãã³ãã¬ãŒãã®éçºããå§ããŸããããããã¯ãããããã¿ã€ãTã«å¯ŸããŠã¹ã¬ããã»ãŒãã§ãããæé©åãããããã¯ããªãŒã¢ã«ãŽãªãºã ã®ã¬ãã«ã§ãã«ãã¹ã¬ããããã©ãŒãã³ã¹ã瀺ããŸãã
ããã«ãããã¯ããªãŒã®ããŒã¿æ§é ã§ãããã¯ã䜿çšããå¿ èŠããããæ°žé ã®ãããããã¯ãçºçããå¯èœæ§ã®ããè€æ°ã®ç°ãªããªããžã§ã¯ããäžåºŠã«ã¢ãããã¯ãã€äžè²«ããŠåŠçããæ©èœãåããŠããŸãã ãã ãããããããã¯ãåŠçããããã®ç¹å¥ãªçžäºæä»ããã¯ã¯ã©ã¹ãéçºããŸãã 次ã«ãç¬èªã®é«æ§èœãªç«¶åã®ãªãshared-mutexãå®è£ ããŸããããã¯ãæšæºã®std :: shared_mutexãããã¯ããã«é«éã§ãã ãããŠãããã«åºã¥ããŠãcontfree_safe_ptr <>ãšåŒã°ããã»ãŒããã€ã³ã¿ãŒsafe_ptr <T>ã®æé©åããŒãžã§ã³ãäœæããŸãã æåŸã«ãããã¯ããªãŒã©ã€ãã©ãªCDSlibãšæ¯èŒããããã©ãŒãã³ã¹ãã¹ããå®æœããŸãã äŸãšããŠcontfree_safe_ptr <std :: map <>>ã䜿çšããŠãCDSlibïŒSkipListMapããã³BronsonAVLTreeMapïŒãšåæ§ã®ããã©ãŒãã³ã¹ã確èªããŸãã
ãã®çµæãã¯ã©ã¹Tãã¹ã¬ããã»ãŒãã«ããããã«ãæéã¯å¿ èŠãããŸããã次ã®ããã«æžãã ãã§ãïŒcontfree_safe_ptr <T> ptr_thread_safe;
ãŸããããã©ãŒãã³ã¹ã¯ãã¯ã©ã¹ã®ã¡ãœããã§1ãæéããã¯ããªãŒã¢ã«ãŽãªãºã ãéçºããŠããå Žåãšã»ãŒåãã§ãã ããã«ãè€æ°ã®contfree_safe_ptr <>ãäžåºŠã«ã¢ãããã¯ã«å€æŽããããšãã§ããŸãã std :: shared_ptr <>ãšåæ§ã«ãã¹ããŒããã€ã³ã¿ãŒã«ã¯åç §ã«ãŠã³ããå«ãŸããŸãã ã³ããŒã§ããŸããæåŸã®ã³ããŒãåé€ãããšãåçã«å²ãåœãŠãããã¡ã¢ãªã¯èªåçã«è§£æŸãããŸãã
æåŸã«ãsafe_ptr.hãã¡ã€ã«ã1ã€æäŸãããŸããããã¯#includeâ safe_ptr.hâãä»ããŠæ¥ç¶ããã®ã«ååãªã®ã§ããã®ã¯ã©ã¹ã䜿çšã§ããŸãã
ãã«ãã¹ã¬ããããŒã¿äº€æã®åºæ¬åå
ãåãã®ãšããã次ã®4ã€ã®å Žåã«ã®ã¿ãç°ãªãã¹ããªãŒã ããåããªããžã§ã¯ããèªã¿åã£ãŠå€æŽã§ããŸãã
1.ããã¯ããŒã¹ã ãªããžã§ã¯ãã¯ããã¯ã«ãã£ãŠä¿è·ãããŠããŸãïŒspin-lockãstdïŒmutexãrecursive_mutexãtimed_mutexãshared_timed_mutexãshared_mutex ...ïŒïŒ en.cppreference.com/mwiki/index.php?title=Special%3ASearch&search=mutex
2.ã¢ãããã¯ã ãªããžã§ã¯ãã®ã¿ã€ãã¯std :: atomic <T>ã§ããããã§ãTã¯ãã€ã³ã¿ãŒãããŒã«ããŸãã¯æŽæ°åïŒstd :: is_integral <T> :: value == trueïŒã§ãããã¿ã€ãTã«å¯ŸããŠCPUã¬ãã«ã§ã¢ãããã¯æäœãååšããå Žåã®ã¿ïŒ en .cppreference.com / w / cpp / atomic / atomic
2 + 1ïŒããã¯ããŒã¹ã®ã¢ãããã¯ïŒãã以å€ã®å Žåãã¿ã€ãTãç°¡åã«ã³ããŒå¯èœãªã¿ã€ããã€ãŸã æ¡ä»¶ãæºããstd :: is_trivially_copyable <T> :: value == trueããã®åŸstd :: atomic <T>ã¯ããã¯ããŒã¹ãšããŠåäœããŸã-ããã¯ã¯å éšã§èªåçã«äœ¿çšãããŸã
3.ãã©ã³ã¶ã¯ã·ã§ã³ã»ãŒãã ãªããžã§ã¯ãã§åäœããããã«å®è£ ãããé¢æ°ã¯ãã¹ã¬ããã»ãŒããªtransaction_safeä¿èšŒãæäŸããŸãïŒãã©ã³ã¶ã¯ã·ã§ã³ã¡ã¢ãªTSïŒ ISO / IEC TS 19841ïŒ2015 ïŒ-å®éšçC ++ïŒïŒ en.cppreference.com/w/cpp/language/transactional_memory
4.ããã¯ããªãŒã ãªããžã§ã¯ããæäœããããã®é¢æ°ã¯ãããã¯ããªãŒã¢ã«ãŽãªãºã ã«åºã¥ããŠå®è£ ãããŸãã ã¹ã¬ããã»ãŒããªããã¯ããªãŒä¿èšŒãæäŸãã
ã¹ã¬ããã»ãŒãã確ä¿ãã4ã€ã®æ¹æ³ããã¹ãŠç¥ã£ãŠããå Žåã¯ããã®ç« ãã¹ãããã§ããŸãã
éé ã§æ€èšããŠãã ããïŒ
ïŒ4ïŒããã¯ããªãŒã¢ã«ãŽãªãºã ã¯éåžžã«è€éã§ãå€ãã®å Žåãåè€éãªã¢ã«ãŽãªãºã ãäœæããã«ã¯ããã€ãã®ç§åŠè«æãå¿ èŠã§ãã ã³ã³ãããæäœããããã®ããã¯ããªãŒã¢ã«ãŽãªãºã ã®äŸïŒunordered_mapãordered_mapãqueue ...ãããã³ç§åŠäœåãžã®ãªã³ã¯ã¯ãã©ã€ãã©ãªã«ãããŸã-Concurrent Data StructuresïŒCDSïŒã©ã€ãã©ãªïŒ github.com/khizmax/libcds
ãããã¯éåžžã«é«éã§ä¿¡é Œæ§ã®é«ããã«ãã¹ã¬ããããŒã¿æ§é ã§ããããããŸã§ã¯C ++ 17ãŸãã¯C ++ 20æšæºã©ã€ãã©ãªã«å«ããèšç»ã¯ãªãããã©ããæšæºã«ã¯å«ãŸããŠããŸããïŒ www.open-std.org/JTC1/SC22/WG21
ïŒ3ïŒ C ++æšæºã®å®éšéšåã«ãã©ã³ã¶ã¯ã·ã§ã³ã»ãŒããå«ãŸããããšãèšç»ãããŠããããã§ã«ISO / IEC TS 19841ïŒ2015æšæºã®ãã©ããããããŸãïŒ www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4514.pdf
ãã ãããã¹ãŠã®STLã³ã³ããã§ããããã©ã³ã¶ã¯ã·ã§ã³ã»ãŒãã«ãªãäºå®ã¯ãããŸããã ããšãã°ãã³ã³ããstd ::ãããã¯ãã©ã³ã¶ã¯ã·ã§ã³çã«å®å šã§ããããã«èšç»ãããŠããŸããã ãã©ã³ã¶ã¯ã·ã§ã³ã»ãŒããšããŠå®çŸ©ãããŠããé¢æ°ã¯ãbeginãendãsizeãmax_sizeãemptyã®ã¿ã§ãã ãã ããã¹ã¬ããã»ãŒãé¢æ°ãšããŠå®çŸ©ãããŠããŸããïŒæ€çŽ¢ãå€æŽãæ¿å ¥ã ãŸãããã©ã³ã¶ã¯ã·ã§ã³ã»ãŒããªã¡ã³ããŒé¢æ°ã䜿çšããŠç¬èªã®ãªããžã§ã¯ããå®è£ ããããšã¯ã決ããŠç°¡åã§ã¯ãããŸãããããã§ãªããã°ãstd :: mapã«å¯ŸããŠè¡ãããŸãã
ïŒ2ïŒã¢ãããã¯ã ãã®ã¢ãããŒãã¯ãã§ã«C ++ 11ã§æšæºåãããŠãããç°¡åã«äœ¿çšã§ããŸãã ããšãã°ãå€æ°std :: atomic shared_val;ã宣èšããã ãã§ãã 次ã«ããªã³ã¯ãŸãã¯ãã®ãã€ã³ã¿ãŒãããã€ãã®ã¹ã¬ããã«æž¡ããã¡ã³ããŒé¢æ°ãšstdãä»ãããã¹ãŠã®åŒã³åºã::ã¢ãããã¯æŒç®åã¯ã¹ã¬ããã»ãŒãã«ãªããŸãïŒ[3] coliru.stacked-crooked.com/a/9d0219a5cfaa3cd5
ã¡ã³ããŒé¢æ°ãå°çšã¡ã³ããŒé¢æ°ïŒ en.cppreference.com/w/cpp/atomic/atomic
ã¢ãããã¯å€æ°ã§è€æ°ã®æäœãå®è¡ããå Žåã1ã€ã®åŒãŸãã¯è€æ°ã®åŒã§éèŠã§ã¯ãªããå¥ã®ã¹ã¬ããããã®å€æ°ã®å€ãå€æŽã§ããããšãç解ããããšãéèŠã§ãã ãããã£ãŠãããã€ãã®æäœã®ã¢ãããã¯å®è¡ã«ã¯ãCASé¢æ°ïŒCompare-And-SwapïŒcompare_exchange_weakïŒïŒã«åºã¥ãããã¯ããªãŒã¢ãããŒãã䜿çšãããŸã-ããªãã¡ïŒã¢ãããã¯å€æ°ããããŒã«ã«å€æ°ïŒold_local_valïŒã«å€ãèªã¿åããå¿ èŠãªæäœã®ã»ãããå®è¡ããçµæãæžã蟌ã¿ãŸãããŒã«ã«å€æ°ïŒnew_local_valïŒã«è¿œå ããCASé¢æ°ã§æåŸã«ã¢ãããã¯å€æ°ã®çŸåšã®å€ãåæïŒold_local_valïŒãšæ¯èŒããããããçãããªãå Žåããµã€ã¯ã«ãå床å®è¡ããããããçããå Žåããã®éã«ä»ã®ã¹ã¬ãããå€æŽãè¡ããã次ã«å€æŽããããšãæå³ããŸãåå䟡 å€æ°ãæ°ããå€ïŒnew_local_valïŒã«å€æŽããŸãã ããã«ã1ã€ã®æäœcompare_exchange_weakïŒïŒã§æ¯èŒãšå²ãåœãŠãè¡ããŸããããã¯ã¢ãããã¯é¢æ°ã§ãããå®å šã«å®è¡ããããŸã§ã誰ãå€æ°ã®å€ãå€æŽã§ããŸããïŒ[4] coliru.stacked-crooked.com/a/aa52b45150e5eb0a
ãã®ãµã€ã¯ã«ã¢ãããŒãã¯ã楜芳çããããã³ã°ãšããŠç¥ãããŠããŸãã æ²èŠ³çããã¯ãšåŒã°ããïŒã¹ãã³ããã¯ããã¥ãŒããã¯ã¹...
ãããŠããã®ãµã€ã¯ã«ã®ãã¹ãŠã®æäœãæ²èŠ³çããã¯ãªãã§å®è¡ãããå Žåããã®ãããªã¢ã«ãŽãªãºã ã¯ããã¯ããªãŒãšåŒã°ããŸãã
å€ãã®å Žåããã€ã³ã¿ãŒã¯ã¢ãããã¯CASé¢æ°ã«çœ®ãæããããŸããã€ãŸããæ°ããã¡ã¢ãªãå²ãåœãŠãããå¯å€ãªããžã§ã¯ããããã«ã³ããŒããããã®ãã€ã³ã¿ãŒãååŸããããã®ã³ããŒã«å¯ŸããŠäžé£ã®ã¢ã¯ã·ã§ã³ãå®è¡ãããæåŸã«ãæ°ãããªããžã§ã¯ãã®ãã€ã³ã¿ãŒãžã®å€ããã€ã³ã¿ãŒãCASé¢æ°ã«çœ®ãæããããŸãå¥ã®ã¹ã¬ãããå€ããã€ã³ã¿ãŒãå€æŽããªãã£ããšãã ãããããã€ã³ã¿ãŒãå¥ã®ã¹ã¬ããã«ãã£ãŠå€æŽãããå Žåããã¹ãŠãåã³ç¹°ãè¿ãããŸãã
ã ABA ããšåŒã°ããåé¡ãããå¯èœæ§ããããŸãã ä»ã®ã¹ã¬ããããã€ã³ã¿ã2åå€æŽãã2åç®ã¯ãã€ã³ã¿ãå ã®å€ã«å€æŽããããããã®ã¢ãã¬ã¹ã§ã¯ä»ã®ã¹ã¬ããããã§ã«ãªããžã§ã¯ããåé€ããŠæ°ãããªããžã§ã¯ããäœæããå Žåã ã€ãŸã ãã€ã³ã¿ã®å€ãå¥ã®ãªããžã§ã¯ããæããŸãããå€ãå€æŽãããŠããªãããšããããããªããžã§ã¯ãã¯çœ®ãæããããªãã£ããšæããŸãã ãã®åé¡ã解決ããæ¹æ³ã¯å€æ°ãããŸããããšãã°ãLL / SCãRCUãhazard_pointerãã¬ããŒãžã³ã¬ã¯ã¿ãŒãªã©ã§ãã
ã¢ãããã¯ã¯ãã¹ã¬ããéã§ããŒã¿ã亀æããæéã®æ¹æ³ã§ãã ããã«ããã¹ãŠã®ã¢ãããã¯æäœã«å¯ŸããŠãããå³ãããªãé«éãªã¡ã¢ãªããªã¢ã䜿çšã§ããŸããããã«ã€ããŠã¯ã以äžã§è©³çŽ°ã«æ€èšããŸãã ããã©ã«ãã§ã¯ãæãå®å šã§å³å¯ãªäžŠã¹æ¿ãããªã¢ã䜿çšãããŸãïŒstd :: memory_order_seq_cstã ããããåè¿°ããããã«ãã¢ãããã¯å€æ°ã䜿çšããŠè€éãªããžãã¯ãå®è£ ããã«ã¯å€å€§ãªåŽåãå¿ èŠã§ãã
ïŒ2ïŒ-ïŒ1ïŒã¢ãããã¯ããã³ããã¯ããŒã¹ã
ãã ããè€æ°ã®å€æ°ãäžåºŠã«ã¢ãããã¯ã«èªã¿åããŸãã¯å€æŽããå¿ èŠãããå Žåã¯ãstd :: atomic aãbãc; ããã¯ããªãŒã¢ã«ãŽãªãºã ãå®è£ ããŠABAã®åé¡ã解決ããããªãå Žåã¯ãããã¯ã䜿çšããå¿ èŠããããŸãã ã»ãšãã©ã®CPUã®ã¢ãããã¯ããã»ããµCASæ©èœã¯ãæ倧64ãããå¹ ã®å€æ°ã1ã€ã ãå€æŽããããã©ããã確èªã§ããŸããããã®æç¹ã§å¥ã®å€æ°ãå€æŽãããŠããå¯èœæ§ããããŸãã 解決çïŒstd :: atomic <T>ã䜿çšãããšãT-ä»»æã®ãµã€ãºã®æ§é ã®ã¿ã€ãã«äœ¿çšã§ããŸãã
C ++æšæºã§ã¯ãstd :: atomic <T>ã«åTã䜿çšããå¯èœæ§ãå°å ¥ãããŠããŸããããã¯ããç°¡åã«ã³ããŒå¯èœãªåããã€ãŸã std :: is_trivially_copyable <T> :: value == trueã®æ¡ä»¶ãæºãã
C ++ æšæºã¯ãŒãã³ã°ãã©ãããããã°ã©ãã³ã°èšèªC ++ N4606ã®æšæº2016-07-12ã®å 容 ïŒ www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf
§29.5/ 1
ãžã§ããªãã¯ã¯ã©ã¹ãã³ãã¬ãŒãatomic <T>ããããŸãã ãã³ãã¬ãŒãåŒæ°Tã®åã¯ç°¡åã«ã³ããŒã§ãããã®ã§ãªããã°ãªããŸãã ïŒ3.9ïŒã [泚ïŒéçã«åæåããããšãã§ããªãååŒæ°ã¯ã䜿çšãé£ããå ŽåããããŸãã -çµäºããŒã]
§3.9/ 9
ã¹ã«ã©ãŒåãç°¡åã«ã³ããŒå¯èœãªã¯ã©ã¹åïŒ9é ïŒããã®ãããªåã®é åãããã³ãããã®åã®cv修食ããŒãžã§ã³ïŒ3.9.3ïŒã¯ãç°¡åã«ã³ããŒå¯èœãªåãšç·ç§°ãããŸã
ããããããã»ããµãŒã®ã¢ãããã¯CASé¢æ°ããæ倧64ãããå¹ ã®å€æ°ã1ã€ã ãå€æŽããããã©ããããã§ãã¯ã§ãããããã32ãããã®å€æ°ã3ã€ããå ŽåãCASé¢æ°ã¯std :: atomic <T>ã§ã©ã®ããã«æ©èœããŸããïŒ CASããã³ä»ã®ãã¹ãŠã®é¢æ°ã¯ãTïŒç°¡åã«ã³ããŒå¯èœãªåïŒã«å¯ŸããŠãstd :: atomic <T>ã®æšæºå®è£ ã«å«ãŸããããã¯ïŒstd :: mutexãŸãã¯ãã®ä»ïŒãèªåçã«äœ¿çšããŸãã
ããã€ãã®å€æ°ã®ã¢ãããã¯ãªå€æŽ-å€æ°struct Tããæ§é äœã䜿çšã§ããŸã{int priceãcountãtotal; }; std :: atomic <T>ãã³ãã¬ãŒãã®åãšããŠã
äŸïŒ[5] coliru.stacked-crooked.com/a/bdfb3dc440eb6e51
åºåäŸïŒ10ã7ã70
ãã®äŸã§ã¯ãããæç¹ã§ã®æåŸã®å€70ã¯ãæåã®2ã€ã®å€10 * 7-ã®ç©ã«çãããªããŸãã æ§é å šäœã¯ååçã«ã®ã¿å€åããŸãã
x86çšã®gccããã³clangã®ãã®ã³ãŒãã¯ã-latomicãã©ã°ã䜿çšããŠã³ã³ãã€ã«ããå¿ èŠããããŸã
ããã«ãstd :: atomic <T> shared_valãžã®ååŒã³åºãã shared_val.is_lock_freeïŒïŒ== falseé¢æ°ã®å€ããæãããªããã«ãå éšã§ããã¯ãçºçããŸãã
ã€ãŸã ã°ããŒãã«ã«ããªããã£ãã¹ãã£ãã¯ããã¯ïŒã«ãŒãïŒã䜿çšããã¢ãããã¯å€æ°ã«ã¢ã¯ã»ã¹ãããšãã«ããŒã«ã«ã§2ã€ã®ãã·ãã¹ãã£ãã¯ããã¯ã䜿çšããŸãããå€ãå€ãååŸããŠCASé¢æ°ãåŒã³åºããŸãã
ïŒ1ïŒããã¯ããŒã¹ã
ãã ããã¿ã€ãTã«ã¯å¿ é ã®ç°¡åã«ã³ããŒå¯èœãªæ¡ä»¶ããããããäœæããTã®ã¿ã€ãã«ã¯std :: atomic <T>ã䜿çšã§ããŸããããã¹ãŠã®STLã³ã³ããã®äžã§ãstd :: array <>ã®ã¿ã䜿çšã§ããŸãã ããšãã°ãstd :: atomic <std :: map <intãint >>ã¯äœ¿çšã§ããŸããã type std :: map <>ã¯ããã®ãã³ãã¬ãŒãã®åŒæ°ã«å¯ŸããŠãç°¡åã«ã³ããŒã§ããŸããã ãŸããç¬èªã®ã¯ã©ã¹ãstd :: atomic <T>ã®ã¿ã€ãTãšããŠäœ¿çšããããšã¯ã§ããŸããã
ãã®å Žåãèªåã§ãã¥ãŒããã¯ã¹ãªããžã§ã¯ããäœæããå ±æãªããžã§ã¯ãã䜿çšããåã«æ¯åãããã¯ãããã®åŸããã¯è§£é€ããå¿ èŠããããŸãã ã³ã³ã»ããïŒ en.cppreference.com/w/cpp/concept/Mutex
C ++ã«ã¯ã次ã®ãã¥ãŒããã¯ã¹ããããŸããstd:: mutexãstd :: recursive_mutexãstd :: timed_mutexãstd :: recursive_timed_mutexãstd :: shared_timed_mutexãstd :: shared_mutexã ãããã®è©³çŽ°ã«ã€ããŠã¯ã en.cppreference.com / w / cpp / threadãåç §ããŠãã ãã ã
ããšãã°ãã¹ã¬ããéã§å ±æããããªããžã§ã¯ãstd :: map <intãT>ãäœæãããããä¿è·ãããã¥ãŒããã¯ã¹ãäœæããŠãè€æ°ã®ã¹ã¬ããã§ãªã³ã¯ãæž¡ããŸãã ãããŠãåã¹ã¬ããã§ãå ±æãªããžã§ã¯ã[6] coliru.stacked-crooked.com/a/a97e905d54ae1fbbã䜿çšããåã«ãã¥ãŒããã¯ã¹ããããã¯ããŸãã
RAIIã€ãã£ãªã ã䜿çšããŠãããã¯ããŸããstd:: lock_guard <std :: mutex> lockïŒmtxïŒ; -ãã®ãªããžã§ã¯ããäœæãããšããã®ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãã¥ãŒããã¯ã¹ããããã¯ãããªããžã§ã¯ãã®å¯¿åœãçµäºãããšããã¹ãã©ã¯ã¿ããã¥ãŒããã¯ã¹ãããã¯è§£é€ããŸãã ãããã£ãŠãããã¯ã解é€ããããšãå¿ããªãã§ãããã ãã¹ãã©ã¯ã¿ã¯èªåçã«åŒã³åºãããŸãã
ãããããŸã 4ã€ã®äž»ãªåé¡ããããŸãã
- ãããããã¯-ã¹ã¬ãã1ãmtx1ããããã¯ããã¹ã¬ãã2ãmtx2ããããã¯ããããã«ã³ãŒããèšè¿°ãããšãã¹ã¬ãã1ã®ããã¯ãä¿æããŠããéãmtx2ããã£ããã£ããããšããã¹ã¬ãã2ã¯mtx1ããã£ããã£ããããšããŸãæ°žé ã«ã ããã¯ããªãŒã¢ã«ãŽãªãºã ã§ã¯ãã®åé¡ã¯ãããŸããããããã¯ããªãŒã䜿çšããŠããžãã¯ãå®è£ ããããšã¯ã§ããŸãããè€æ°ã®ã³ã³ããã®äžè²«ããã¢ãããã¯ãªå€æŽã®äŸã䜿çšããŠããã瀺ããŸãã
- mutexãããã¯ãããŠããéã«ãstd :: lock_guard lockã®å¯¿åœãããé·ã寿åœãæã€å ±æãªããžã§ã¯ããžã®ãªã³ã¯ããã€ã³ã¿ãŒã«å²ãåœãŠãå Žåãããã¯è§£é€åŸããã®ãã€ã³ã¿ãŒã«ãã£ãŠå ±æãªããžã§ã¯ããåç §ã§ããŸã-ããã¯ããŒã¿ç«¶åã®åé¡ã«ã€ãªãããŸããã€ãŸã å ±æãªããžã§ã¯ãã®äžè²«æ§ã®ãªãç¶æ ãããã³èª€åäœãŸãã¯ããã°ã©ã ã®ã¯ã©ãã·ã¥ã å ±æãªããžã§ã¯ãããåãåã£ãã€ãã¬ãŒã¿ããã¥ãŒããã¯ã¹ã®ããã¯ã解é€ããåŸã«äœ¿çšãããå Žåãåãããšãèµ·ãããŸãã
- ãã¥ãŒããã¯ã¹ãæ··åšãããŠãå¥ã®ãªããžã§ã¯ãïŒããŒã¿ã®ç«¶åïŒãä¿è·ãããã¥ãŒããã¯ã¹ããããã¯ã§ããŸãã
- ãã¥ãŒããã¯ã¹ãé©åãªå Žæã«ããã¯ããã®ãå¿ããã ãã§ã-ããŒã¿ã®ç«¶åã
ãã€ã³ã¿ãŒã€ãã£ãªã ã®åšå²ã§å®è¡
RAIIã®ã€ãã£ãªã ã«å ããŠãå¥ã®èå³æ·±ãã€ãã£ãªã ããããŸããããã¯ãæåŸã®2ã€ã®åé¡ã«å¯ŸåŠããã®ã«åœ¹ç«ã€Execute Around Pointerã§ãã
- ãã¥ãŒããã¯ã¹ã¯ãªããžã§ã¯ããšããŒãžãããåå¥ã®ãã¥ãŒããã¯ã¹ã§ã¯ãªãããªããžã§ã¯ãèªäœããããã¯ã§ããŸã
- ãã¥ãŒããã¯ã¹ã¯ãä¿è·ããããªããžã§ã¯ãã®ã¯ã©ã¹ã®ã¡ã³ããŒã«ã¢ã¯ã»ã¹ãããšãã«èªåçã«ãããã¯ãããŸãâããã«ãåŒã®æéäžã¯ãããã¯ãããŸãã
ãã®çµæããã¥ãŒããã¯ã¹ãããã¯ããããšãå¿ããããšãã§ããããã¥ãŒããã¯ã¹ãæ··åããããšã¯ã§ããŸããã
ãªããžã§ã¯ããã¹ã¬ããã»ãŒãã«ãã
Execute Around Pointer Idiomã¯ãå®è¡ã®é åºãå³å¯ã«å®çŸ©ãããæåãªã€ãã£ãªã ã§ãããèŠèŠåãããã®ã³ã°ãŸã§ã®ããŸããŸãªç®çã«äœ¿çšãããŸããen.wikibooks.org / wiki / More_C%2B%2B_Idioms/ Execute- Around_Pointer
äŸïŒ[7] coliru.stacked-crooked.com/a/4f3255b5473c73cc
execute_around<std::vector<int>> vecc(10, 10); int res = my_accumulate(vecc->begin(), vecc->end(), 0);
æåã«ãexecute_aroundå ã®mutexããããã¯ãããããã·ã¿ã€ãã®äžæãªããžã§ã¯ããäœæãããŸãã次ã«ãbeginïŒïŒããã³endïŒïŒé¢æ°ã«ãã£ãŠè¿ãããå埩åãé¢æ°ã«æž¡ãããmy_accumulateïŒïŒé¢æ°ãå®è¡ãããŸãã ãããã³ãããã®ãã¹ãã©ã¯ã¿ããã¥ãŒããã¯ã¹ã®ããã¯ã解é€ããŸãã
詳现ã«ã€ããŠã¯ãèšäºã C ++ Patterns Executing Around Sequencesããåç §ããŠãã ããã Kevlin Henney ïŒ hillside.net/europlop/HillsideEurope/Papers/ExecutingAroundSequences.pdf
C ++ã«ã¯ãæšæºÂ§1.9ïŒ13ïŒã®å®è¡é åºãå³å¯ã«å®çŸ©ãã2ã€ã®å®çŸ©ããããŸããåã«é åºä»ããããåŸãšé åºä»ããããåŸã§ãã 以äžã®æšæºããã®åŒçšã§ã¯ããåã«ã·ãŒã±ã³ã¹ãã2å衚瀺ãããŸãã
Execute Around Pointer Idiomã®ãã¹ãŠã®ã¢ã¯ã·ã§ã³ã®å®è¡ã®ååãšé åºã¯ãããã°ã©ãã³ã°èšèªC ++ N4606 2016-07-12ã®C ++ Working Draft Standardã«å³å¯ã«èšè¿°ãããŠããŸããwww.open-std.org/ jtc1 / sc22 / wg21 / docs / papers / 2016 /n4606.pdf
ãŸããæšæºãã5ã€ã®åŒçšç¬Šãä»ãã次ã«ååŒçšç¬ŠãExecute Around Pointer Idiomã®åäœãã©ã®ããã«èª¬æãããã瀺ããŸãã
1. rawãã€ã³ã¿ãŒä»¥å€ã®ãã¹ãŠã®ã¿ã€ãã®Tã®å ŽåïŒx-> mã¯ïŒx.operator->ïŒïŒïŒ-> mãšè§£éãããŸãã ã€ãŸã åŒïŒx-> mïŒã¯äœåãå±éãããŸãïŒïŒx.operator->ïŒïŒãoperator->ïŒïŒïŒ-> mçã®ãã€ã³ã¿ãååŸããŸããæå³åŒãåã3ã€ã®äŸïŒ[8] coliruã stacked-crooked.com/a/dda2474024b78a0b
§13.5.6
operator->ã¯ããã©ã¡ãŒã¿ãŒãåããªãééçã¡ã³ããŒé¢æ°ã§ãªããã°ãªããŸããã ->ã䜿çšããã¯ã©ã¹ã¡ã³ããŒã¢ã¯ã»ã¹æ§æãå®è£ ããŸãã
postfix-expression->ãã³ãã¬ãŒãopt id-expression
åŸçœ®åŒ->æ¬äŒŒãã¹ãã©ã¯ã¿å
åŒx-> mã¯ãT ::æŒç®å->ïŒïŒãååšããæŒç®åãæé©äžèŽé¢æ°ãšããŠéžæãããŠããå Žåãã¿ã€ãTã®ã¯ã©ã¹ãªããžã§ã¯ãxã«å¯ŸããŠïŒx.operator->ïŒïŒïŒ-> mãšããŠè§£éãããŸãããªãŒããŒããŒã解決ã¡ã«ããºã ïŒ13.3ïŒã
2.é¢æ°ãåŒã³åºããããšãããšãããããã€ã³ã©ã€ã³ãã§ãã£ãŠããé¢æ°ã®åŒæ°ãèšç®ãããåŒããã®èšç®ãšå¹æã¯ãé¢æ°ã®æ¬äœãå®è¡ãããåã«çµ¶å¯Ÿã«å®è¡ãããŸãã
§1.9 / 16
é¢æ°ãåŒã³åºããšãïŒé¢æ°ãã€ã³ã©ã€ã³ã§ãããã©ããã«é¢ä¿ãªãïŒãåŒæ°åŒããŸãã¯åŒã³åºãããé¢æ°ãæå®ããæ¥å°ŸèŸåŒã«é¢é£ä»ãããããã¹ãŠã®å€ã®èšç®ãšå¯äœçšã¯ãæ¬äœã®ãã¹ãŠã®åŒãŸãã¯ã¹ããŒãã¡ã³ãã®å®è¡åã«ã·ãŒã±ã³ã¹ãããŸãé¢æ°ãšåŒã°ããŸãã
3.äžæãªããžã§ã¯ããç Žæ£ãããåã«ãåŒå šäœãå®å šã«å®è¡ãããŸãã
§1.9 / 10
void f() { if (S(3).v()) // full-expression includes lvalue-to-rvalue and // int to bool conversions, performed before // temporary is deleted at end of full-expression { } }
4.åŒå šäœãå®å šã«å®è¡ãããåŸãäžæãªããžã§ã¯ãã¯äœæãããé åºãšã¯éã®é åºã§ç Žæ£ãããŸãã
§1.9è泚8
12.2ã§æå®ãããŠããããã«ãå®å šãªåŒãè©äŸ¡ãããåŸãäžæãªããžã§ã¯ãã®ãã¹ãã©ã¯ã¿é¢æ°ã®ãŒã以äžã®åŒã³åºãã®ã·ãŒã±ã³ã¹ããéåžžã¯åäžæãªããžã§ã¯ãã®æ§ç¯ã®éã®é åºã§è¡ãããŸãã
5.äžæãªããžã§ã¯ããåŒå šäœã®æåŸã§ç Žæ£ãããªã3ã€ã®ã±ãŒã¹-é åã®èŠçŽ ãåæåããã2ã€ã®ã±ãŒã¹ãäžæãªããžã§ã¯ããžã®ãªã³ã¯ãäœæããã3çªç®ã®ã±ãŒã¹ã
§12.2äžæãªããžã§ã¯ã
§12.2 / 5
å®å šãªè¡šçŸã®çµãããšã¯ç°ãªãæç¹ã§äžæãç Žæ£ããã3ã€ã®ã³ã³ããã¹ãããããŸãã æåã®ã³ã³ããã¹ãã¯ãããã©ã«ãã®ã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºãããŠã察å¿ããåæååããªãé åã®èŠçŽ ãåæåããå Žåã§ãïŒ8.6ïŒã 2çªç®ã®ã³ã³ããã¹ãã¯ãé åå šäœãã³ããŒãããŠããéã«é åã®èŠçŽ ãã³ããŒããããã«ã³ããŒã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºãããå Žåã§ãïŒ5.1.5ã12.8ïŒã ã©ã¡ãã®å Žåã§ããã³ã³ã¹ãã©ã¯ã¿ãŒã«1ã€ä»¥äžã®ããã©ã«ãåŒæ°ãããå Žåãããã©ã«ãåŒæ°ã§äœæããããã¹ãŠã®ãã³ãã©ãªãŒã®ç Žæ£ã¯ã次ã®é åèŠçŽ ïŒååšããå ŽåïŒã®æ§ç¯ã®åã«ã·ãŒã±ã³ã¹ãããŸãã 3çªç®ã®ã³ã³ããã¹ãã¯ãåç §ãäžæã«ãã€ã³ãããããšãã§ãã
ããšãã°ãåçŽåãããã¯ã©ã¹execute_around <>ããããŸã
template<typename T, typename mutex_type = std::recursive_mutex> class execute_around { std::shared_ptr<mutex_type> mtx; std::shared_ptr<T> p; void lock() const { mtx->lock(); } void unlock() const { mtx->unlock(); } public: class proxy { std::unique_lock<mutex_type> lock; T *const p; public: proxy (T * const _p, mutex_type& _mtx) : lock(_mtx), p(_p) { std::cout << "locked \n";} proxy(proxy &&px) : lock(std::move(px.lock)), p(px.p) {} ~proxy () { std::cout << "unlocked \n"; } T* operator -> () {return p;} const T* operator -> () const {return p;} }; template<typename ...Args> execute_around (Args ... args) : mtx(std::make_shared<mutex_type>()), p(std::make_shared<T>(args...)) {} proxy operator -> () { return proxy(p.get(), *mtx); } const proxy operator -> () const { return proxy(p.get(), *mtx); } template<class Args> friend class std::lock_guard; };
ãããŠããã³ãã¬ãŒãã¯ã©ã¹execute_around <>ã次ã®ããã«äœ¿çšããŸããäŸïŒ[45] coliru.stacked-crooked.com/a/d2e02b61af6459f5
int main() { typedef execute_around<std::vector<int>> T; T vecc(10, 10); int res = my_accumulate(vecc->begin(), vecc->end(), 0); return 0; }
ãã®åŸãæåŸã®åŒã¯ãããã€ãã®å€æãéããŠæ¬¡ã®åœ¢åŒã«çž®å°ã§ããŸãã
1.æšæºã®æåã®åŒçšã«ãããšãx-> mã¯ïŒx.operator->ïŒïŒïŒ-> mãšããŠè§£éãããŸãã
int res = my_accumulate( (vecc.operator->())->begin(), (vecc.operator->())->end(), 0);
2.ä»¥æ¥ vecc.operator->ïŒïŒã¯ãäžæãªããžã§ã¯ãT :: proxyïŒïŒãè¿ããŸãã
int res = my_accumulate( T::proxy(vecc.p.get(), *vecc.mtx)->begin(), T::proxy(vecc.p.get(), *vecc.mtx)->end(), 0);
3.ããã«ãåŒçšç¬Š2ã3ã4ã«ãããšããããã·ã¿ã€ãã®äžæãªããžã§ã¯ãã¯ãé¢æ°ã®å®è¡ãéå§ãããåã«äœæãããé¢æ°ã®çµäºåŸïŒåŒå šäœã®çµäºåŸïŒã«ç Žæ£ãããŸãã
T::proxy tmp1(vecc.p.get(), *vecc.mtx); // lock-1 std::recursive_mutex T::proxy tmp2(vecc.p.get(), *vecc.mtx); // lock-2 std::recursive_mutex int res = my_accumulate(tmp1->begin(), tmp2->end(), 0); tmp2.~ T::proxy(); // unlock-2 std::recursive_mutex tmp1.~ T::proxy(); // unlock-1 std::recursive_mutex
4.ããäžåºŠæåã®åŒçšã«ãããšïŒ
â¢tmp1-> beginïŒïŒã¯ïŒtmp1.operator->ïŒïŒïŒ-> beginïŒïŒãšåçã§ã
â¢tmp1.operator->ïŒïŒã¯pãè¿ããŸã
ãã®çµæãpã¯std :: vectoråã®ãªããžã§ã¯ããžã®shared_ptrãã€ã³ã¿ãŒã§ãã
typedef execute_around<std::vector<int>> T; T vecc(10, 10); T::proxy tmp1(vecc.p.get(), *vecc.mtx); // lock-1 std::recursive_mutex T::proxy tmp2(vecc.p.get(), *vecc.mtx); // lock-2 std::recursive_mutex int res = my_accumulate(tmp1.p->begin(), tmp2.p ->end(), 0); tmp2.~ T::proxy(); // unlock-2 std::recursive_mutex tmp1.~ T::proxy(); // unlock-1 std::recursive_mutex
4ã€ã®ã¹ãããã§ããã¹ãŠã®ã€ãã£ãªã ã¢ã¯ã·ã§ã³ã®å³å¯ãªã·ãŒã±ã³ã¹ã説æããŸããã æšæºã§ã¯ãäžæå€æ°tmp1ãštmp2ã®äœæã®çžäºé åºãä¿èšŒãããŠããªãããšã«æ³šæããŠãã ããã tmp2ãæåã«äœæããŠããtmp1ãäœæã§ããŸãããããã«ããããã°ã©ã ã®ããžãã¯ã¯å€æŽãããŸããã
æšæºã®5çªç®ã®åŒçšãåç §ããŠããªãããšã«æ³šæããŠãã ãããããã¯ããªããžã§ã¯ãã®åé€ã®æéãäžãããããã®ãšç°ãªããããããªã3ã€ã®ã±ãŒã¹ãèšè¿°ããŸãããããŠãæã ãèŠãããã«ããããã®ã±ãŒã¹ã®ã©ããç§ãã¡ã®ãã®ã«å¯Ÿå¿ããããšãã§ããŸãããæšæºåŒçšã®æåã®2ã€ã®ã±ãŒã¹ã¯ãé åã®åæåãŸãã¯ã³ããŒã§ãããäžæãªããžã§ã¯ãã®å¯¿åœãçããã3çªç®ã®ã±ãŒã¹ã¯ããªã³ã¯ãžã®ãªã³ã¯ã®ååšã«ããäžæãªããžã§ã¯ãã®å¯¿åœã®å»¶é·ã§ãã
ã¹ã¬ããã»ãŒãé£æ³é å
åæããŸããä»»æã®åãæž¡ãããšãã§ããsafe_ptr <>ãã³ãã¬ãŒãã¯ã©ã¹ãããã°äŸ¿å©ã§ããã®çµæãã¹ã¬ããã»ãŒããªçµæã®åãååŸã§ããŸããïŒ
safe_ptr <std :: map <std :: stringãstd :: pair <std :: stringãint> >> safe_map_strings;
ããã«ãé£æ³é åãžã®ãã€ã³ã¿ãŒã䜿çšããŠãã®ãªããžã§ã¯ããæäœã§ããŸããstd:: shared_ptr <std :: map <std :: stringãstd :: pair <std :: stringãint> >>
ããããä»ã§ã¯å®å šã«äœæ¥ã§ããŸãç°ãªãã¹ããªãŒã ããååŸããåã ã®åŒã¯ã¹ã¬ããã»ãŒãã«ãªããŸãïŒ
(*safe_map_strings)["apple"].first = "fruit"; (*safe_map_strings)["potato"].first = "vegetable"; safe_map_strings->at("apple").second = safe_map_strings->at("apple").second * 2; safe_map_strings->find("potato")->second.second++;
ã¹ã¬ããã»ãŒããªé£æ³ã®å®å šã«æ©èœããäŸã瀺ããŸãïŒstd :: map <>ã[9]
coliru.stacked-crooked.com/a/5def728917274b22
#include <iostream> #include <string> #include <vector> #include <memory> #include <mutex> #include <thread> #include <map> template<typename T, typename mutex_t = std::recursive_mutex, typename x_lock_t = std::unique_lock<mutex_t>, typename s_lock_t = std::unique_lock<mutex_t >> class safe_ptr { typedef mutex_t mtx_t; const std::shared_ptr<T> ptr; std::shared_ptr<mutex_t> mtx_ptr; template<typename req_lock> class auto_lock_t { T * const ptr; req_lock lock; public: auto_lock_t(auto_lock_t&& o) : ptr(std::move(o.ptr)), lock(std::move(o.lock)) { } auto_lock_t(T * const _ptr, mutex_t& _mtx) : ptr(_ptr), lock(_mtx){} T* operator -> () { return ptr; } const T* operator -> () const { return ptr; } }; template<typename req_lock> class auto_lock_obj_t { T * const ptr; req_lock lock; public: auto_lock_obj_t(auto_lock_obj_t&& o) : ptr(std::move(o.ptr)), lock(std::move(o.lock)) { } auto_lock_obj_t(T * const _ptr, mutex_t& _mtx) : ptr(_ptr), lock(_mtx){} template<typename arg_t> auto operator [] (arg_t arg) -> decltype((*ptr)[arg]) { return (*ptr)[arg]; } }; void lock() { mtx_ptr->lock(); } void unlock() { mtx_ptr->unlock(); } friend struct link_safe_ptrs; template<typename mutex_type> friend class std::lock_guard; //template<class... mutex_types> friend class std::lock_guard; // C++17 public: template<typename... Args> safe_ptr(Args... args) : ptr(std::make_shared<T>(args...)), mtx_ptr(std::make_shared<mutex_t>()) {} auto_lock_t<x_lock_t> operator -> () { return auto_lock_t<x_lock_t>(ptr.get(), *mtx_ptr); } auto_lock_obj_t<x_lock_t> operator * () { return auto_lock_obj_t<x_lock_t>(ptr.get(), *mtx_ptr); } const auto_lock_t<s_lock_t> operator -> () const { return auto_lock_t<s_lock_t>(ptr.get(), *mtx_ptr); } const auto_lock_obj_t<s_lock_t> operator * () const { return auto_lock_obj_t<s_lock_t>(ptr.get(), *mtx_ptr); } }; // --------------------------------------------------------------- safe_ptr<std::map<std::string, std::pair<std::string, int> >> safe_map_strings_global; void func(decltype(safe_map_strings_global) safe_map_strings) { //std::lock_guard<decltype(safe_map_strings)> lock(safe_map_strings); (*safe_map_strings)["apple"].first = "fruit"; (*safe_map_strings)["potato"].first = "vegetable"; for (size_t i = 0; i < 10000; ++i) { safe_map_strings->at("apple").second++; safe_map_strings->find("potato")->second.second++; } auto const readonly_safe_map_string = safe_map_strings; std::cout << "potato is " << readonly_safe_map_string->at("potato").first << " " << readonly_safe_map_string->at("potato").second << ", apple is " << readonly_safe_map_string->at("apple").first << " " << readonly_safe_map_string->at("apple").second << std::endl; } int main() { std::vector<std::thread> vec_thread(10); for (auto &i : vec_thread) i = std::move(std::thread(func, safe_map_strings_global)); for (auto &i : vec_thread) i.join(); std::cout << "end"; int b; std::cin >> b; return 0; }
çµè«ïŒ
ãããã¯éè65042ããªã³ãŽã¯æç©81762
ããªã³ãŽã¯æç©81716ã
ãããã¯éè84716ããªã³ãŽã¯æç©84720ã
ãããã¯éè86645ããªã³ãŽã¯æç©86650ã
ãããã¯éè90288ããªã³ãŽã¯æç©90291ã
ãããã¯éè93070ããªã³ãŽã¯ãã«ãŒã93071
ãžã£ã¬ã€ã¢ã¯éè93810ããªã³ãŽã¯ãã«ãŒã93811
ãžã£ã¬ã€ã¢ã¯éè95788ããªã³ãŽã¯ãã«ãŒã95790
ãžã£ã¬ã€ã¢ã¯éè98951ããªã³ãŽã¯ãã«ãŒã98952
ãžã£ã¬ã€ã¢ã¯éè100000ããªã³ãŽã¯ãã«ãŒã100000
çµãã
ãããã£ãŠã2ã€ã®çµè«ïŒ
- 100000 , 10 -. , , operator -> auto_lock_t auto_lock_obj_t , , - â data-race: [10] coliru.stacked-crooked.com/a/45d47bcb066adf2e
- 10000 , , .. . ã€ãŸãåã€ã³ã¯ãªã¡ã³ãæŒç®å++ã®åã«ããã¥ãŒããã¯ã¹ããããã¯ãããã€ã³ã¯ãªã¡ã³ãã®çŽåŸã«ããã¯è§£é€ããããã®åŸãã€ã³ã¯ãªã¡ã³ããå®è¡ããå¥ã®ã¹ã¬ããã«ãã£ãŠãã¥ãŒããã¯ã¹ããããã¯ãããå¯èœæ§ããããŸãããåã¹ã¬ããã®éå§æã«ãstd :: lock_guard <> ã䜿çšããŠãã¹ã¬ããé¢æ°ã®å®è¡ãçµäºãããŸã§mutexãããã«ããã¯ã§ããŸãããŸããã¹ã¬ãããæ¬äŒŒäžŠåã§ã¯ãªãé£ç¶ããŠå®è¡ãããå Žåãäœããã®çµæã衚瀺ãããŸãïŒ a / cc252270fa9f7a78
ã©ã¡ãã®çµè«ããsafe_ptr <T>ã¹ããŒããã€ã³ã¿ãŒã¯ã©ã¹ãã³ãã¬ãŒãããTåã®ä¿è·ãªããžã§ã¯ãã®ã¹ã¬ããã»ãŒããèªåçã«æäŸããããšã確èªããŸãã
è€æ°ã®ãªããžã§ã¯ãã®ã¹ã¬ããå®å šæ§ãååæ§ãäžè²«æ§ã
äžè²«æ§ãç¶æãããããã«ãè€æ°ã®ãªããžã§ã¯ããäžåºŠã«ã¢ãããã¯ã«å€æŽããæ¹æ³ã瀺ããŸãããããŠãããããã€å¿ èŠã«ãªãããã©ã®ããã«è¡ããããããè¡ãããªãå Žåã«äœãèµ·ãããã瀺ããŸãã
ç°¡åãªäŸã次ã«ç€ºããŸãã2ã€ã®ããŒãã«ããããšããŸãã
- user_accountsïŒINT user_idãSTRING user_nameãINT moneyïŒ -åã¯ã©ã€ã¢ã³ãã®éé¡ãå«ãããŒãã«-user_idã§ãœãŒã
- cash_flowsïŒINT unique_idãINT src_idãINT dst_idãINT timeãINT moneyïŒ - ãéã®åãã瀺ãããŒãã«-åã¬ã³ãŒãã«å¯ŸããŠ2ã€ã®é£æ³é åãåç §ããããã£ãŒã«ãsrc_idãšãã£ãŒã«ãdst_idã§ãœãŒããããŸã
// 1-st table struct user_accounts_t { std::string user_name; int64_t money; user_accounts_t(std::string u, int64_t m) : user_name(u), money(m) {} }; std::map<uint64_t, user_accounts_t> user_accounts; // 2-nd table struct cash_flows_t { uint64_t unique_id, src_id, dst_id, time; int64_t money; }; std::atomic<uint64_t> global_unique_id; // SQL-sequence std::multimap<uint64_t, std::shared_ptr<cash_flows_t>> cash_flows_src_id; std::multimap<uint64_t, std::shared_ptr<cash_flows_t>> cash_flows_dst_id;
DBMSïŒRDBMSïŒã«é¢ããŠïŒ
- user_idãã£ãŒã«ãã«ã€ã³ããã¯ã¹ãããæåã®ããŒãã«ã¯ãã€ã³ããã¯ã¹æ§æããŒãã«ïŒOracleïŒãŸãã¯ã¯ã©ã¹ã¿ãŒåã€ã³ããã¯ã¹ä»ãããŒãã«ïŒMS SQLïŒã§ãã
- 2çªç®ã®ããŒãã«ã¯ã1ã€ã®src_idãã£ãŒã«ããš1ã€ã®dst_idãã£ãŒã«ãã«ãããã2ã€ã®é åºä»ããããã€ã³ããã¯ã¹ãæã€ããŒãã«ã§ãã
å®éã®ã¿ã¹ã¯ã§ã¯ãããŒãã«ã«é¡§å®¢ã®æ°çŸäžã®ã¬ã³ãŒããšãã£ãã·ã¥ãããŒã®æ°ååã®ã¬ã³ãŒããå«ãŸããå ŽåããããŸãããã®å Žåããã£ãŒã«ãuser_idãsrc_idãdst_idã®ã€ã³ããã¯ã¹ã¯ããããã®æ€çŽ¢ãæ°åäžåé«éåãããããéåžžã«å¿ èŠã§ãã
3人ã®ãŠãŒã¶ãŒãã3ã€ã®äžŠåãããŒã§3ã€ã®ã¿ã¹ã¯ãå®è¡ããèŠæ±ãåãåã£ããšããŸã
ã1. move_moneyïŒïŒ -ã¹ããªãŒã ã¯ãããã¯ã©ã€ã¢ã³ãããå¥ã®ã¯ã©ã€ã¢ã³ãã«ééããŸã
- aïŒ1人ã®ã¯ã©ã€ã¢ã³ããããéãããã
- bïŒåãéé¡ãå¥ã®ã¯ã©ã€ã¢ã³ãã«è¿œå ãã
- cïŒééååŒãžã®ãã€ã³ã¿ãid-sourceãã£ãŒã«ãã«ãã£ãŠã€ã³ããã¯ã¹ã«è¿œå ãããŸã
- dïŒid-destinationãã£ãŒã«ãã«ãã£ãŠåããããŒãã©ã³ã¶ã¯ã·ã§ã³ãžã®ã€ã³ããã¯ã¹ãã€ã³ããã¯ã¹ã«è¿œå ãããŸãïŒå®éã®ã¿ã¹ã¯ã§ã¯ããã¯å¿ èŠãããŸããããããšãã°ãããè¡ããŸãïŒ
2. show_total_amountïŒïŒ -ãã¹ãŠã®é¡§å®¢ã®éé¡ã衚瀺ããŸã
- aïŒãµã€ã¯ã«ã§ã¯ãåã¯ã©ã€ã¢ã³ãã調ã¹ãŠãã¹ãŠã®ãéãåèšããŸã
3. show_user_money_on_timeïŒïŒ -æå®ãããuser_idã§ã®ã¯ã©ã€ã¢ã³ãã®éé¡ãäžåºŠã«è¡šç€ºããŸã
- aïŒçä¿¡-æã ã¯ã©ã€ã¢ã³ãã«éããããã¹ãŠã®ãéãåèšããŸãïŒid-sourceãã£ãŒã«ãã®ã€ã³ããã¯ã¹ã䜿çšïŒ
- bïŒäºå®-ãã°ããããŠããã¯ã©ã€ã¢ã³ãã«æ®ããããã¹ãŠã®ãéãåèšããŸãïŒid-destinationãã£ãŒã«ãã®ã€ã³ããã¯ã¹ã䜿çšïŒ
- cïŒuser_money-ã¯ã©ã€ã¢ã³ãããçŸåšã®ãéãååŸãã
- dïŒuser_ user_money-çä¿¡+çºä¿¡-ããã¯ããã®æç¹ã§ã®ã¯ã©ã€ã¢ã³ãã®éé¡ã§ã
ããšãã°ãCPUã³ã¢ãå¥ã®ã¹ã¬ããã«æäŸããããã«ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã«ãã£ãŠã¹ã¬ããããã€ã§ãäžæãããå¯èœæ§ãããããšãããã£ãŠããŸããæãå±éºãªããšã¯ããããéåžžã«ãŸãã«çºçããããšã§ããããããã°äžã«ããã«ééããããšã¯ãããŸãããããã€ãã¯ã¯ã©ã€ã¢ã³ãã§çºçãããããããŒã¿ç«¶åã«ã€ãªããå Žåãéèã·ã¹ãã ã§ãéãåçŽã«æ¶å€±ããå¯èœæ§ããããŸãã
ãããã£ãŠããšã©ãŒãããã«ç¢ºèªããããã«ãæãéèŠãªå Žæã§ã¹ã¬ãããæ°ããªç§éã¹ãªãŒãç¶æ ã«ããåŸ æ©é¢æ°ãæå³çã«è¿œå ããŸãã
safe_ptr <>ã¹ã¬ããã»ãŒãã䜿çšããŠuser_accountsãcash_flows_src_idãcash_flows_dst_idããŒãã«ãäœæããŸãããããã«ããããã°ã©ã å šäœãã¹ã¬ããã»ãŒãã«ãªããŸããïŒ
[12] coliru.stacked-crooked.com/a/5bbba59b63384a2b
<<<ã§ããŒã¯ãããããã°ã©ã åºåã®ãã¡ã€ã³è¡ããèŠãŠã¿ãŸãããã
åæããŒãã«safe_user_accountsïŒ
at = 0 <<<
1 => John Smithã100
2 => John Ramboã150
-start transaction ... show_total_amountïŒïŒ
1 => John Smithã100
2 => John Ramboã100
çµæïŒãã¹ãŠã®ã¢ã«ãŠã³ãtotal_amount = 200 <<<
-ãã©ã³ã¶ã¯ã·ã§ã³ãéå§... show_user_money_on_timeïŒïŒ
1 => John Smithã150ãat time = 0 <<<
2ã€ã®ãšã©ãŒãããã«è¡šç€ºãããŸãã
- æåã¯ãåèšã§ïŒ2人ã®ïŒãã¹ãŠã®ãŠãŒã¶ãŒã250ã®ãéãæã£ãŠããŠãshow_total_amountïŒïŒé¢æ°ã¯200ã®ã¿ã瀺ããå¥ã®50ã¯ã©ããã«æ¶ããŸãã
- æé= 0ã§ããŠãŒã¶ãŒ1ã«100ã®ãéããããshow_user_money_on_timeïŒïŒé¢æ°ã誀ã£ãçµæã瀺ããŸãã-ãŠãŒã¶ãŒ1ã«ã¯æé= 0ã§150ã®ãéããããŸãã
åé¡ã¯ãååæ§ãåã ã®ããŒãã«ãšã€ã³ããã¯ã¹ã®ã¬ãã«ã§ã®ã¿èŠ³å¯ãããéèšã§ã¯ãªããããäžè²«æ§ã䟵害ãããããšã§ãã解決çã¯ãã¢ãããã¯ã«å®è¡ããå¿ èŠããããã¹ãŠã®æäœã®éã䜿çšãããŠãããã¹ãŠã®ããŒãã«ãšã€ã³ããã¯ã¹ãããã¯ããããšã§ããããã«ãããäžè²«æ§ãç¶æãããŸãã
è¿œå ãããè¡ã¯é»è²ã§åŒ·èª¿è¡šç€ºãããŸãã
æ£ããäŸïŒ[13] coliru.stacked-crooked.com/a/c8bfc7f5372dfd0c
ããã°ã©ã ã®åºåã§ã<<<ã®ããŒã¯ãä»ãããã¡ã€ã³ã©ã€ã³ããèŠãŠã¿ãŸãããã
åæããŒãã«safe_user_accountsïŒ
at = 0 <<<
1 => John Smithã100
2 => John Ramboã150
çµæïŒãã¹ãŠã®ã¢ã«ãŠã³ãtotal_amount = 250 <<<
1 => John Smithã100ãat = 0 <<<
ããã§ãã¹ãŠãçå®ã«ãªãããã¹ãŠã®ã¯ã©ã€ã¢ã³ãã®åèšéé¡ã¯250ã§ãããã¯ã©ã€ã¢ã³ã1ããã®éé¡ã¯æé0ã§100ã§ããã
ã€ãŸã1ã€ã®ãªããžã§ã¯ãã§ã¯ãªãã3ã€ã®ãªããžã§ã¯ãã§å³åº§ã«æäœãã¢ãããã¯ã«å®è¡ã§ããã©ã®æäœã§ãããŒã¿ã®äžè²«æ§ãç¶æãããŸããã
ãã ããããã§ã¯å¥ã®åé¡ãçºçããå¯èœæ§ããããŸããããªããŸãã¯é¢æ°ã®ããããã®å¥ã®éçºè ãç°ãªãé åºã§ã³ã³ãããã¥ãŒããã¯ã¹ããããã¯ãããšããããããã¯ãšåŒã°ããç¶æ³ãçºçããå¯èœæ§ããããŸãã
äžèšã®æ£ããäŸã§ã¯ãé¢æ°move_moneyïŒïŒãšshow_user_money_on_timeïŒïŒã®äž¡æ¹ã®mutexãåãé åºã§ãããã¯ããŸããã
- lock1ïŒsafe_user_accountsïŒ
- lock2ïŒsafe_cash_flows_src_idïŒ
- lock3ïŒsafe_cash_flows_dst_idïŒ
ããã§ã¯ãåé¢æ°ã®ã³ã³ããå ã®ãã¥ãŒããã¯ã¹ãç°ãªãé åºã§ãããã¯ãããšã©ããªããèŠãŠã¿ãŸãããã
â¢move_moneyïŒïŒ
- lock2ïŒsafe_cash_flows_src_idïŒ
- lock3ïŒsafe_cash_flows_dst_idïŒ
- lock1ïŒsafe_user_accountsïŒ
â¢show_user_money_on_timeïŒïŒ
- lock3ïŒsafe_cash_flows_dst_idïŒ
- lock2ïŒsafe_cash_flows_src_idïŒ
- lock1ïŒsafe_user_accountsïŒ
move_moneyïŒïŒé¢æ°ã¯lock2ãããã¯ããlock3ã解æŸãããŠããã¯ããããŸã§åŸ æ©ããŸããshow_user_money_on_timeïŒïŒé¢æ°ã¯lock3ãããã¯ããlock2ã解æŸãããŠããã¯ãããã®ãåŸ ã¡ãŸãããããŠã圌ãã¯æ°žé ã«ãäºããåŸ ã¡ãŸãã
äŸïŒ[14] coliru.stacked-crooked.com/a/0ddcd1ebe2be410b
çµè«ïŒ
åæããŒãã«safe_user_accountsïŒ
at = 0 <<<
1 => John Smithã100
2 => John Ramboã150
-start transaction ... move_moneyïŒïŒ
-start transaction ... show_total_amountïŒïŒ
1 => John Smithã100
2 => Johnã©ã³ããŒã150
ã€ãŸãé¢æ°move_moneyïŒïŒããã³show_user_money_on_timeïŒïŒã¯å®äºããããããããã¯ç¶æ ã§æ°žä¹ ã«åæ¢ããŸããã
4ã€ã®è§£æ±ºçããã
ãŸãã1.ãã¹ãŠã®æ©èœã®éçºè ã¯ãåžžã«åãé åºã§mutexããããã¯ãããã¹ãç¯ããŸãã-ããã¯éåžžã«ä¿¡é Œã§ããªãåæã§ã
2ãæåã«ãã¢ãããã¯ã«äœ¿çšããããã¹ãŠã®ãªããžã§ã¯ãã1ã€ã®æ§é ã«çµåããæ§é åstruct all_t {std :: map <intãint> m1;ã®å®å šãªãã€ã³ã¿ãŒã䜿çšããŸãã std :: multimap <intãint> m2; ...}; safe_ptr <all_t> safe_all_obj; -ãã ããããã2ã€ã®ã³ã³ãããæåã«å¥ã ã«ã®ã¿äœ¿çšããå Žåãsafe_ptr <map <intãint >> m1; safe_ptr <multimap <intãint >> m2;ãããŠããã§ã«å€ãã®ã³ãŒããäœæãããããã1ã€ã®mutexã§ä¿è·ããã1ã€ã®æ§é ã«çµåããããšã決å®ããå Žåãããšãã°ïŒ2ïŒã®m2->ã®ä»£ããã«ããããã䜿çšãããã¹ãŠã®å Žæãæžãæããå¿ èŠããããŸã; safe_all_obj-> m2.atïŒ5ïŒ;ãå¿ èŠã§ãã倧éã®ã³ãŒããæžãæããããšã¯ããŸã䟿å©ã§ã¯ãããŸããã
3ãäžç·ã«äœ¿çšãããsafe_ptr <>ãçµã¿åãããŠãåãååž°ãã¥ãŒããã¯ã¹ã䜿çšããŸãããã®åŸããããã¯ãããé åºã¯é¢ä¿ãªãããããã®ãªããžã§ã¯ãã®äžè²«æ§ã¯åžžã«ä¿æããããããããã¯ã¯çºçããŸããããããè¡ãã«ã¯ã1è¡è¿œå ããã ãã§ã-ããã¯éåžžã«äŸ¿å©ã§ãããã ããããã«ããããã©ãŒãã³ã¹ãäœäžããå¯èœæ§ããããŸããçŸåšãã³ã³ããã®1ã€ããããã¯ãããšãããã«é¢é£ä»ããããŠãããã¹ãŠã®ã³ã³ãããåžžã«ãããã¯ãããŸããäžè²«æ§ã¯å¿ èŠãªãå Žåã§ãåŸãããŸãããçç£æ§ã¯äœäžããŸããäŸïŒ[15] coliru.stacked-crooked.com/a/2a6f1535e0b95f7b
ã³ãŒãå ã®ãã¹ãŠã®å€æŽã¯ã1è¡ã ã
ã§ãã
çµè«-äž»ãªè¡ã衚瀺ãããŸãïŒ
åæããŒãã«safe_user_accountsïŒ
at = 0 <<<
1 => John Smithã100
2 => John Ramboã150
çµæïŒãã¹ãŠã®ã¢ã«ãŠã³ãtotal_amount = 250 <<<
1 => John Smithã100ãat = 0 <<<
4.åmutexãããã¯ããã¿ã€ã ã¢ãŠãæéãèšå®ããŠãããŸããŸãªã¿ã€ãã®è€æ°ã®ãã¥ãŒããã¯ã¹ã«å¯ŸããŠããã¯ãäžåºŠã«äœ¿çšã§ããŸãããã®éã«å°ãªããšã1ã€ã®mutexãããã¯ã§ããªãå Žåã以åã«ããã¯ããããã¹ãŠã®mutexã®ããã¯ã解é€ãããã¹ã¬ããã¯ãã°ããåŸ æ©ããŠãããã¹ãŠã®mutexãé çªã«ãããã¯ããããšããŸãããããè¡ãã«ã¯ãã³ã³ããlock_timed_any_infinity lock_allïŒsafe_cash_flows_src_idãsafe_cash_flows_dst_idãsafe_user_accountsïŒã䜿çšããåã«1è¡è¿œå ããã ãã§ããã³ã³ãããã¥ãŒããã¯ã¹ããããã¯ããé åºã¯é¢ä¿ãããŸãããäŸïŒ[16] coliru.stacked-crooked.com/a/93206f216ba81dd6
ã€ãŸã ç°ãªãã·ãŒã±ã³ã¹ã§ãã¥ãŒããã¯ã¹ããããã¯ããŠãïŒ
- lock_timed_any_infinityã䜿çšããå Žåããããããã¯ã¯çºçããŸããïŒ[17] coliru.stacked-crooked.com/a/7ac7640918228090
- åæ§ã®äŸã§ãlock_guard <>ã䜿çšãããšããããããã¯ãçºçããŸãïŒ[18] coliru.stacked-crooked.com/a/a281f90299771434
ãããã£ãŠãããã¯ïŒããã¯ïŒã®å©ããåããŠãæ°žé ã®ãããããã¯ãªãã§ä¿èšŒãããComposableã®åé¡ã解決ããŸããïŒhttps : //en.wikipedia.org/wiki/Lock_ (computer_science) #Lack_of_composability
ã³ã³ããŒã¶ãã«ãšãããããã¯
ãªããªãäžèšã®ã¹ã¬ããã»ãŒãã®ããã«ããã¯ã䜿çšãããã®åŸãã¢ã«ãŽãªãºã ã¯ããã¯ããŒã¹ãšåŒã°ããŸãã
ããããããã¯ããªãŒã³ã³ããã«ãããããã¯ããªãããã©ã³ã¶ã¯ã·ã§ã³ã¡ã¢ãªã«åºã¥ããã¢ã«ãŽãªãºã ããªããMSDBïŒããã¯ããŒã¹ã®ILïŒãšOracleïŒãã«ãããŒãžã§ã³åæå®è¡å¶åŸ¡ïŒã®ææ°ã®DBMSã«ãããããã¯ãããããã¹ãŠãæ¬åœã«åªããŠããŸãã
ããã¯ããªãŒã¢ã«ãŽãªãºã ã§ã¯ãããã€ãã®ã³ã³ãããã¢ãããã¯ã«å€æŽããããšã¯ã§ããŸããã RDBMSïŒRDBMSïŒã«ã¯ãããã¯ããŒã¹ã®ã¢ã«ãŽãªãºã ãšåæ§ã«ãããããã¯ã«é¢ãããã¹ãŠã®åé¡ããããå€ãã®å Žåãããã¯ã¿ã€ã ã¢ãŠããŸãã¯ããã¯ã°ã©ããéããŠåãæ¹æ³ã§åé¡ã解決ããŸãããŸããC ++æšæºã®æ°ãããã©ã³ã¶ã¯ã·ã§ã³ã»ãŒãã»ã¯ã·ã§ã³ã§ã¯ãstd :: map <>ãªã©ã®è€éãªã¢ã«ãŽãªãºã ã®ã¹ã¬ããã»ãŒããªäœ¿çšãèš±å¯ãããŠããŸããã
ããã¯ããªãŒã¢ã«ãŽãªãºã ã«ã¯ãComposableæäœãšããããããã£ããããŸãã-ããã€ãã®ããã¯ããªãŒã¢ã«ãŽãªãºã ã®ã¢ãããã¯ãªäœ¿çšã§ãã ã€ãŸãããã€ãã®ããã¯ããªãŒããŒã¿æ§é ãäžåºŠã«å€æŽããããã¢ãããã¯ã«èªã¿åãããšã¯ã§ããŸãããããšãã°ãlibCDSã®ããã¯ããªãŒé£æ³é åã³ã³ããã䜿çšã§ããŸããŸãããããã¯åå¥ã«ã¹ã¬ããã»ãŒãã«ãªããŸãããã ããè€æ°ã®ããã¯ããªãŒã³ã³ããã§æäœãäžåºŠã«ã¢ãããã¯ã«å®è¡ããäžè²«æ§ãç¶æããå Žåã¯ããããè¡ãããšãã§ããŸããããããã®APIã¯ãè€æ°ã®ã³ã³ããã§åæã«æäœããããã®ããã¯ããªãŒæ©èœãæäŸããŸãããããã³ã³ãããå€æŽãŸãã¯èªã¿åãäžã«ãå¥ã®ã³ã³ããã¯ãã®æç¹ã§ãã§ã«å€æŽãããŠããŸãããããåé¿ããã«ã¯ãããã¯ã䜿çšããå¿ èŠããããŸãããã®å Žåããã§ã«ããã¯ã«åºã¥ããã³ã³ããã«ãªã£ãŠãããããããã¯ããŒã¹ã®ã¢ã«ãŽãªãºã ã®ãã¹ãŠã®åé¡ãã€ãŸããããããã¯ã®å¯èœæ§ããããŸããããã«ã1ã€ã®ã³ã³ããã®ã¿ã䜿çšããå Žåã«ããã¯ã䜿çšãããå ŽåããããŸãã
- libcds.sourceforge.net/doc/cds-api/namespacecds_1_1sync.html
- github.com/khizmax/libcds/tree/master/cds/lock
- github.com/khizmax/libcds/tree/master/cds/sync
MSSQLïŒããã¯ããŒã¹ïŒãOracleïŒãã«ãããŒãžã§ã³åæå®è¡å¶åŸ¡ïŒãªã©ã®ãã©ã³ã¶ã¯ã·ã§ã³RDBMSã§ã¯ãããã¯ã䜿çšãããããããããããã¯ã®åé¡ãçºçããŸããããã¯ãããšãã°ãããã¯ã°ã©ããäœæããŠåšæçãªæåŸ å€ãèŠã€ããããèšå®ããããšã§èªåçã«è§£æ±ºã§ããŸãããã¯åŸ æ©ã¿ã€ã ã¢ãŠãtblããcolãéžæããŸããæŽæ°åŸ æ©30ã®idïŒ....ïŒãã¿ã€ã ã¢ãŠããæéåãã«ãªã£ãå ŽåããŸãã¯ããã¯ã°ã©ãã§ãããããã¯ãèŠã€ãã£ãå Žåãããããã®ãã©ã³ã¶ã¯ã·ã§ã³ã®ããŒã«ããã¯ïŒããŒã«ããã¯ïŒãçºçããŸãããã®ãã©ã³ã¶ã¯ã·ã§ã³ã«ãã£ãŠæ¢ã«è¡ããããã¹ãŠã®å€æŽãå ã«æ»ãããããã¯ãããŠãããã¹ãŠã®ããã¯ã解é€ããŠããããã©ã³ã¶ã¯ã·ã§ã³ãæåããïŒãããŠäœåºŠãïŒå®è¡ããããšãã§ããŸãã
- Oracle Databaseãªã³ã©ã€ã³ããã¥ã¡ã³ã11gãªãªãŒã¹1ïŒ11.1ïŒ-ãããããã¯ïŒdocs.oracle.com/cd/B28359_01/server.111/b28318/consist.htm#i5337
Oracleããã¯ïŒdocs.oracle.com/cd/B28359_01/server.111 /b28318/consist.htm#i5249ã芧ã®
ãšããããã¹ãŠã®åŒã§æä»çã§äºææ§ã®ãªãããã¯ã䜿çšãããŠããŸãïŒInsert / Update / Delete / Select-For-Update - MSSQLã«ãããããããã¯ã®æ€åºãšçµäºïŒhttps : //technet.microsoft.com/en-us/library/ms178104(v= sql.105) .aspx
MS SQLããã¯ïŒhttps : //technet.microsoft.com/en-us/ã©ã€ãã©ãª/ ms186396ïŒv = sql.105ïŒ.aspx
ãã©ã³ã¶ã¯ã·ã§ã³ã¡ã¢ãªã¯ãããã¯ããªãŒã³ã³ãããšã¯ç°ãªããå€ãã®ã³ã³ãã/ããŒã¿ã§ã¢ãããã¯ã«åäœã§ããŸãã ã€ãŸããã©ã³ã¶ã¯ã·ã§ã³ã¡ã¢ãªã«ã¯ãComposableæäœããããã£ããããŸããå éšã§ã¯ãæ²èŠ³çããã¯ïŒãããããã¯ç«¶åã®å¯èœæ§ïŒãŸãã¯æ¥œèŠ³çããã¯ïŒç«¶åä¿®æ£ãšç«¶åä¿®æ£ã®ç«¶åã®å¯èœæ§ãé«ãïŒã®ããããã䜿çšãããŸãããŸãã競åãçºçããå Žåããã©ã³ã¶ã¯ã·ã§ã³ã¯èªåçã«ãã£ã³ã»ã«ãããæåããç¹°ãè¿ãããŸããããã«ã¯ããã¹ãŠã®æäœã®ç¹°ãè¿ããç¹°ãè¿ãããŸããããã«ã¯å€å€§ãªãªãŒããŒãããã䌎ããŸãã CPUã¬ãã«ã§ããŒããŠã§ã¢ãã©ã³ã¶ã¯ã·ã§ã³ã¡ã¢ãªãäœæããããšã§ãããã®ãªãŒããŒããããåæžããããšããŠããŸããããããŸã§ã®ãšããã蚱容ã§ããããã©ãŒãã³ã¹ã瀺ãå®è£ ã¯ãããŸããã C ++æšæºã§ã¯ãTransactional Memoryãå«ããããšãçŽæãããŠããŸãããå°æ¥çã«ã®ã¿ããããŸã§ã¯å®éšçã§ãããstd :: mapã®æäœããµããŒãããŠããŸãããã€ãŸããããŸã§ã®ãšããããã¹ãŠã¯çè«çã«ã®ã¿çŸãããã®ã§ããããããå°æ¥ãããã¯éåžžã®åææ¹æ³ã眮ãæããå¯èœæ§ããããŸãã
åèšïŒ
- ããã¯ããŒã¹ã®ã¢ã«ãŽãªãºã ã¯ãå®è£ äžã«ãã®ãããªæ©äŒãçµã¿èŸŒãŸããŠããªãå Žåã¯ã³ã³ãã€ã«ãããŸãããããã®ãããªæ©äŒã¯å®è£ ã§ããåã®ã»ã¯ã·ã§ã³ã§æ£åžžã«å®è£ ããŸããã
- ããã¯ããªãŒã¢ã«ãŽãªãºã ã¯ã³ã³ãã€ã«ããããããã¯ãªãã§ãªã³ã¯ããããšã¯å§åçãªäœæ¥ã§ãããããã¯ã䜿çšãããšãã®ãããªã¢ã«ãŽãªãºã ã¯ããã¯ããªãŒã§ã¯ãªããªããæ°žé ã®ãããããã¯ã®ãªã¹ã¯ããããŸãã
- RDBMSïŒMSSQLïŒããã¯ããŒã¹ã®ILïŒããã³OracleïŒMVCCïŒ-ããã¯ã°ã©ããŸãã¯ã¿ã€ã ã¢ãŠããä»ããŠåé€ã§ãããããããã¯ãå¯èœ
- C ++æšæºã®å®éšéšåããã®ãã©ã³ã¶ã¯ã·ã§ã³ã¡ã¢ãªã¯ããããŸã§ã®ãšãããæãåçŽãªã¢ã«ãŽãªãºã ã§ã®ã¿äœ¿çšããããã«å¶éãããŠãããstd :: map <>ã¡ãœãããªã©ã®ã¢ã«ãŽãªãºã ã䜿çšããããšã¯ã§ããŸããã
çŸåšã®çµè«ïŒé«æ§èœã瀺ããã¹ãŠã®ã¿ã€ãã®ã¢ã«ãŽãªãºã ãšã·ã¹ãã ã«ãããããã¯ã®åé¡ããããè€æ°ã®ããŒã¿æ§é ãåæã«é¢äžããŠãããããsafe_ptr <>ã®2ã€ã®ãœãªã¥ãŒã·ã§ã³ãææ¡ããŸãã
- static link_safe_ptrs tmp_linkïŒsafe_user_accountsãsafe_cash_flows_src_idãsafe_cash_flows_dst_idïŒ; -è€æ°ã®ã³ã³ããã«1ã€ã®ãã¥ãŒããã¯ã¹ã䜿çšãã
- lock_timed_any_infinity lock_allïŒsafe_cash_flows_src_idãsafe_cash_flows_dst_idãsafe_user_accountsïŒ;-ããã¯ã¿ã€ã ã¢ãŠãã䜿çšããæéã®çµããã«ãã¹ãŠãããã¯è§£é€ããŠãå床ããã¯ãè©Šè¡ããŸã
safe_ptr <>ã«1ã€ã®ã³ã³ãããšååž°ãã¥ãŒããã¯ã¹ã®ã¿ã䜿çšãããŠããå Žåãsafe_ptr <>ã§ãããããã¯ã¯äžå¯èœã§ãããããããã¯ã«ã¯ãå°ãªããšã2ã€ã®ååž°mutexïŒãŸãã¯1ã€ã®éååž°ïŒãå¿ èŠã§ãã
æ§æå¯èœãªããã¯ããŒã¹ã®ã¢ã«ãŽãªãºã
äžè¬çãªå Žåãããã¯ããŒã¹ã®ããã°ã©ã ã¯æ§æå¯èœã§ã¯ãªããšèããããŸãã 2ã€ã®ããã¯ããŒã¹ã®ããŒã¿æ§é ãååŸãããããã1ã€ãã€ã¢ãããã¯ã«å€æŽããã ãã§ã¯ãåžžã«äžè²«ããç¶æ ã«ãªããŸããã
ããããäžèšã§ã¯ã3ã€ã®ããã¯ããŒã¹ã®ã³ã³ãããŒãç°¡åã«é 眮ããŸããããã©ã®ããã«æåããŸãããïŒãã®ç¹ã«ã€ããŠã¯ããããã«æ確åãããŠããŸã-倪åã§ç€ºããŠããŸãïŒ
Perhaps the most fundamental objection [...] is that lock-based programs do not compose: correct fragments may fail when combined. For example, consider a hash table with thread-safe insert and delete operations. Now suppose that we want to delete one item A from table t1, and insert it into table t2; but the intermediate state (in which neither table contains the item) must not be visible to other threads. Unless the implementor of the hash table anticipates this need, there is simply no way to satisfy this requirement. [...] In short, operations that are individually correct (insert, delete) cannot be composed into larger correct operations.
âãã£ã ã»ããªã¹ä»ããã³ã³ããŒã¶ãã«ã¡ã¢ãªãã©ã³ã¶ã¯ã·ã§ã³ããã»ã¯ã·ã§ã³2ïŒèæ¯ãããŒãž2 [6]
www.microsoft.com/en-us/research/wp-content/uploads/2005/01/2005-ppopp- composable.pdf
å®éã®ãšãããããã¯ããŒã¹ã®ã¢ã«ãŽãªãºã ã¯ãå®è£ äžã«ãã®ãããªæ©äŒãå®ããããŠããªãå Žåã¯ã³ã³ãã€ã«ãããŸãããã€ãŸãããã¯ããŒã¹ã®ããŒã¿æ§é ã¯èªåçã«ã³ã³ãã€ã«ãããŸããããå€éšã®ã¬ã€ã¢ãŠãæäœã®ããã«mutexã«ã¢ã¯ã»ã¹ã§ããå Žåã¯ãããšãã°lock_timed_any_infinityã¯ã©ã¹ã®ããã«æåã§ã³ã³ãã€ã«ã§ããŸãã
ããã¯ããŒã¹ã®safe_ptr <T>ãã³ãã¬ãŒãã¯ã©ã¹ãå®è£ ãããªã³ã¯æäœã䜿çšããŠãããããã¯ããªã³ã¯ããã³è§£æ±ºããå¿ èŠæ§ã®ããã«æäŸãããã¹ãŠã®ã¿ã€ãTã«å¯ŸããŠãlink_safe_ptrsãlock_timed_any_infinityãlock_timed_any_onceãå®è£ ããŸããã
ã§ã¯ããªãããã¯ãšæ²èŠ³çãªããŒãžã§ã³ãéžæããã®ã§ããïŒ
- ããã¯ã¯ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ãšC ++èšèªã®ã¹ã¬ããã»ãŒãã確ä¿ããããã®æšæºã¡ã«ããºã ã§ãã
- ããã¯ã䜿çšãããšãè€æ°ã®ããŒã¿æ§é ã®æ§æå¯èœæ§ãšäžè²«æ§ãå®è£ ã§ããŸãã
- deadlock , , . conflicting modifications, , C++- .
- Tom Kyte is a Senior Technical Architect in Oracle's Server Technology Division â Oracle DB (Multi-Version Concurrency Control): https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:5771117722373
, Lockout Deadlock :
I am a huge fan of so called pessimistic locking . The user has very clearly announced their intent to UPDATE THE DATA. The lockouts they refer to are easily handled with session timeouts (trivial) and the deadlock is so rare and would definitely be an application bug (in both Oracle and RDB).
- Deadlock â . , , lock_timed_any_infinity . , , : link_safe_ptrs std::lock_guard <>.
- ããã¯ã®èªåãšã¹ã«ã¬ãŒã·ã§ã³ã®å¿
èŠããããŸãããããšãã°ãOracle DBã¯ãããå®è¡ããŸãããdocs.oracle.com / cd / B28359_01 / server.111 / b28318 / consist.htmïŒCIHCFHGE
Oracle Databaseã¯ããã¯ããšã¹ã«ã¬ãŒãããŸãããããã¯ã®ãšã¹ã«ã¬ãŒã·ã§ã³ã«ããããããããã¯ã®å¯èœæ§ãå€§å¹ ã«é«ãŸããŸãã
ã¢ã«ãŽãªãºã ãå®è£ ããéã«ãç£æ¥DBMSã®è±å¯ãªçµéšãå®æçã«åç §ããŠãããŸãã
safe_ptr.hã®Safe_ptr <T>ã®
äŸïŒgithub.com/AlexeyAB/object_threadsafe/tree/master/any_object_threadsafe