{"id":3779,"date":"2019-08-13T10:22:25","date_gmt":"2019-08-13T02:22:25","guid":{"rendered":"https:\/\/damogame.cn\/wordpress\/?p=3779"},"modified":"2019-08-13T10:22:25","modified_gmt":"2019-08-13T02:22:25","slug":"c-%e5%b9%b6%e5%8f%91%e7%bc%96%e7%a8%8b%ef%bc%88%e4%b8%83%ef%bc%89%ef%bc%9a%e8%af%bb%e5%86%99%e9%94%81%ef%bc%88read-write-lock%ef%bc%89","status":"publish","type":"post","link":"https:\/\/i007.cc\/wordpress\/archives\/3779","title":{"rendered":"C++ \u5e76\u53d1\u7f16\u7a0b\uff08\u4e03\uff09\uff1a\u8bfb\u5199\u9501\uff08Read-Write Lock\uff09"},"content":{"rendered":"<div class=\"post-topheader custom- pt0\">\n<div class=\"mb20\">\n<div class=\"block-for-right-border\">\n<div class=\"row\">\n<div class=\"col-md-12 col-sm-12 col-xs-12\">\n<div class=\"post-topheader__info\" data-username=\"adam1q84\" data-userslug=\"adam1q84\" data-useravatar=\"https:\/\/avatar-static.segmentfault.com\/183\/944\/1839442818-569cb34c4505f_big64\">\n<p id=\"articleTitle\" class=\"h1 post-topheader__info--title\" data-id=\"1190000006941870\"><a href=\"https:\/\/segmentfault.com\/a\/1190000006941870\">\u539f\u6587\u5730\u5740<\/a><\/p>\n<p class=\"content__tech hidden-xs\">\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"visible-lg\">\n<div class=\"side-widget\"><\/div>\n<\/div>\n<div class=\"article fmt article__content\" data-id=\"1190000006941870\" data-license=\"cc\">\n<p>STL \u548c Boost \u90fd\u63d0\u4f9b\u4e86\u00a0<code>shared_mutex<\/code>\u00a0\u6765\u89e3\u51b3\u300c\u8bfb\u8005-\u5199\u8005\u300d\u95ee\u9898\u3002<code>shared_mutex<\/code>\u00a0\u8fd9\u4e2a\u540d\u5b57\u5e76\u4e0d\u5341\u5206\u8d34\u5207\uff0c\u4e0d\u5982 pthread \u76f4\u547c\u300c\u8bfb\u5199\u9501\u300d\u3002<\/p>\n<p>\u6240\u8c13\u300c\u8bfb\u5199\u9501\u300d\uff0c\u5c31\u662f\u540c\u65f6\u53ef\u4ee5\u88ab\u591a\u4e2a\u8bfb\u8005\u62e5\u6709\uff0c\u4f46\u662f\u53ea\u80fd\u88ab\u4e00\u4e2a\u5199\u8005\u62e5\u6709\u7684\u9501\u3002\u800c\u6240\u8c13\u300c\u591a\u4e2a\u8bfb\u8005\u3001\u5355\u4e2a\u5199\u8005\u300d\uff0c\u5e76\u975e\u6307\u7a0b\u5e8f\u4e2d\u53ea\u6709\u4e00\u4e2a\u5199\u8005\uff08\u7ebf\u7a0b\uff09\uff0c\u800c\u662f\u8bf4\u4e0d\u80fd\u6709\u591a\u4e2a\u5199\u8005\u540c\u65f6\u53bb\u5199\u3002<\/p>\n<p>\u4e0b\u9762\u770b\u4e00\u4e2a\u8ba1\u6570\u5668\u7684\u4f8b\u5b50\u3002<\/p>\n<pre class=\"cpp hljs\"><code class=\"cpp\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Counter<\/span> {<\/span>\r\n<span class=\"hljs-keyword\">public<\/span>:\r\n  Counter() : value_(<span class=\"hljs-number\">0<\/span>) {\r\n  }\r\n\r\n  <span class=\"hljs-comment\">\/\/ Multiple threads\/readers can read the counter's value at the same time.<\/span>\r\n  <span class=\"hljs-built_in\">std<\/span>::<span class=\"hljs-keyword\">size_t<\/span> Get() <span class=\"hljs-keyword\">const<\/span> {\r\n    <span class=\"hljs-built_in\">std<\/span>::shared_lock&lt;<span class=\"hljs-built_in\">std<\/span>::shared_mutex&gt; lock(mutex_);\r\n    <span class=\"hljs-keyword\">return<\/span> value_;\r\n  }\r\n\r\n  <span class=\"hljs-comment\">\/\/ Only one thread\/writer can increment\/write the counter's value.<\/span>\r\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">Increase<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n    <span class=\"hljs-comment\">\/\/ You can also use lock_guard here.<\/span>\r\n    <span class=\"hljs-built_in\">std<\/span>::unique_lock&lt;<span class=\"hljs-built_in\">std<\/span>::shared_mutex&gt; lock(mutex_);\r\n    value_++;\r\n  }\r\n\r\n  <span class=\"hljs-comment\">\/\/ Only one thread\/writer can reset\/write the counter's value.<\/span>\r\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">Reset<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n    <span class=\"hljs-built_in\">std<\/span>::unique_lock&lt;<span class=\"hljs-built_in\">std<\/span>::shared_mutex&gt; lock(mutex_);\r\n    value_ = <span class=\"hljs-number\">0<\/span>;\r\n  }\r\n\r\n<span class=\"hljs-keyword\">private<\/span>:\r\n  <span class=\"hljs-keyword\">mutable<\/span> <span class=\"hljs-built_in\">std<\/span>::shared_mutex mutex_;\r\n  <span class=\"hljs-built_in\">std<\/span>::<span class=\"hljs-keyword\">size_t<\/span> value_;\r\n};<\/code><\/pre>\n<p><code>shared_mutex<\/code>\u00a0\u6bd4\u4e00\u822c\u7684\u00a0<code>mutex<\/code>\u00a0\u591a\u4e86\u51fd\u6570\u00a0<code>lock_shared() \/ unlock_shared()<\/code>\uff0c\u5141\u8bb8\u591a\u4e2a\uff08\u8bfb\u8005\uff09\u7ebf\u7a0b\u540c\u65f6\u52a0\u9501\u3001\u89e3\u9501\uff0c\u800c\u00a0<code>shared_lock<\/code>\u00a0\u5219\u76f8\u5f53\u4e8e\u5171\u4eab\u7248\u7684\u00a0<code>lock_guard<\/code>\u3002<\/p>\n<p>\u5bf9\u00a0<code>shared_mutex<\/code>\u00a0\u4f7f\u7528\u00a0<code>lock_guard<\/code>\u00a0\u6216\u00a0<code>unique_lock<\/code>\u00a0\u5c31\u8fbe\u5230\u4e86\u5199\u8005\u72ec\u5360\u7684\u76ee\u7684\u3002<\/p>\n<p>\u6d4b\u8bd5\u4ee3\u7801\uff1a<\/p>\n<pre class=\"cpp hljs\"><code class=\"cpp\"><span class=\"hljs-built_in\">std<\/span>::mutex g_io_mutex;\r\n\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">Worker<\/span><span class=\"hljs-params\">(Counter&amp; counter)<\/span> <\/span>{\r\n  <span class=\"hljs-keyword\">for<\/span> (<span class=\"hljs-keyword\">int<\/span> i = <span class=\"hljs-number\">0<\/span>; i &lt; <span class=\"hljs-number\">3<\/span>; ++i) {\r\n    counter.Increase();\r\n    <span class=\"hljs-built_in\">std<\/span>::<span class=\"hljs-keyword\">size_t<\/span> value = counter.Get();\r\n\r\n    <span class=\"hljs-built_in\">std<\/span>::lock_guard&lt;<span class=\"hljs-built_in\">std<\/span>::mutex&gt; lock(g_io_mutex);\r\n    <span class=\"hljs-built_in\">std<\/span>::<span class=\"hljs-built_in\">cout<\/span> &lt;&lt; <span class=\"hljs-built_in\">std<\/span>::this_thread::get_id() &lt;&lt; <span class=\"hljs-string\">' '<\/span> &lt;&lt; value &lt;&lt; <span class=\"hljs-built_in\">std<\/span>::<span class=\"hljs-built_in\">endl<\/span>;\r\n  }\r\n}\r\n\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">int<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\r\n  <span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-built_in\">std<\/span>::<span class=\"hljs-keyword\">size_t<\/span> SIZE = <span class=\"hljs-number\">2<\/span>;\r\n\r\n  Counter counter;\r\n\r\n  <span class=\"hljs-built_in\">std<\/span>::<span class=\"hljs-built_in\">vector<\/span>&lt;<span class=\"hljs-built_in\">std<\/span>::thread&gt; v;\r\n  v.reserve(SIZE);\r\n\r\n  v.emplace_back(&amp;Worker, <span class=\"hljs-built_in\">std<\/span>::ref(counter));\r\n  v.emplace_back(&amp;Worker, <span class=\"hljs-built_in\">std<\/span>::ref(counter));\r\n\r\n  <span class=\"hljs-keyword\">for<\/span> (<span class=\"hljs-built_in\">std<\/span>::thread&amp; t : v) {\r\n    t.join();\r\n  }\r\n\r\n  <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-number\">0<\/span>;\r\n}<\/code><\/pre>\n<p>\u8f93\u51fa\uff08\u4ecd\u7136\u662f\u968f\u673a\u6027\u7684\uff09\uff1a<\/p>\n<pre class=\"hljs basic\"><code><span class=\"hljs-symbol\">2978 <\/span><span class=\"hljs-number\">1<\/span>\r\n<span class=\"hljs-symbol\">4114 <\/span><span class=\"hljs-number\">2<\/span>\r\n<span class=\"hljs-symbol\">2978 <\/span><span class=\"hljs-number\">3<\/span>\r\n<span class=\"hljs-symbol\">4114 <\/span><span class=\"hljs-number\">4<\/span>\r\n<span class=\"hljs-symbol\">4114 <\/span><span class=\"hljs-number\">6<\/span>\r\n<span class=\"hljs-symbol\">2978 <\/span><span class=\"hljs-number\">5<\/span><\/code><\/pre>\n<p>\u5f53\u7136\uff0c\u5bf9\u4e8e\u8ba1\u6570\u5668\u6765\u8bf4\uff0c\u539f\u5b50\u7c7b\u578b\u00a0<code>std::atomic&lt;&gt;<\/code>\u00a0\u4e5f\u8bb8\u662f\u66f4\u597d\u7684\u9009\u62e9\u3002<\/p>\n<p>\u5047\u5982\u4e00\u4e2a\u7ebf\u7a0b\uff0c\u5148\u4f5c\u4e3a\u8bfb\u8005\u7528\u00a0<code>shared_lock<\/code>\u00a0\u52a0\u9501\uff0c\u8bfb\u5b8c\u540e\u7a81\u7136\u53c8\u60f3\u53d8\u6210\u5199\u8005\uff0c\u8be5\u600e\u4e48\u529e\uff1f<\/p>\n<p><strong>\u65b9\u6cd5\u4e00<\/strong>\uff1a\u5148\u89e3\u8bfb\u8005\u9501\uff0c\u518d\u52a0\u5199\u8005\u9501\u3002\u8fd9\u79cd\u505a\u6cd5\u7684\u95ee\u9898\u662f\uff0c\u4e00\u89e3\u4e00\u52a0\u4e4b\u95f4\uff0c\u5176\u4ed6\u5199\u8005\u8bf4\u4e0d\u5b9a\u5df2\u7ecf\u4ecb\u5165\u5e76\u4fee\u6539\u4e86\u6570\u636e\uff0c\u90a3\u4e48\u5f53\u524d\u7ebf\u7a0b\u4f5c\u4e3a\u8bfb\u8005\u65f6\u6240\u6301\u6709\u7684\u72b6\u6001\uff08\u6bd4\u5982\u6307\u9488\u3001\u8fed\u4ee3\u5668\uff09\u4e5f\u5c31\u4e0d\u518d\u6709\u6548\u3002<\/p>\n<p><strong>\u65b9\u6cd5\u4e8c<\/strong>\uff1a\u7528\u00a0<code>upgrade_lock<\/code>\uff08\u4ec5\u9650 Boost\uff0cSTL \u672a\u63d0\u4f9b\uff09\uff0c\u53ef\u4ee5\u5f53\u505a\u00a0<code>shared_lock<\/code>\u00a0\u7528\uff0c\u4f46\u662f\u5fc5\u8981\u65f6\u53ef\u4ee5\u76f4\u63a5\u4ece\u8bfb\u8005\u300c\u5347\u7ea7\u300d\u4e3a\u5199\u8005\u3002<\/p>\n<div class=\"widget-codetool\">\n<div class=\"widget-codetool--inner\"><\/div>\n<\/div>\n<pre class=\"cpp hljs\"><code class=\"cpp\">{\r\n  <span class=\"hljs-comment\">\/\/ Acquire shared ownership to read.<\/span>\r\n  boost::upgrade_lock&lt;boost::shared_mutex&gt; upgrade_lock(shared_mutex_);\r\n\r\n  <span class=\"hljs-comment\">\/\/ Read...<\/span>\r\n\r\n  <span class=\"hljs-comment\">\/\/ Upgrade to exclusive ownership to write.<\/span>\r\n  boost::upgrade_to_unique_lock&lt;boost::shared_mutex&gt; unique_lock(upgrade_lock);\r\n\r\n  <span class=\"hljs-comment\">\/\/ Write...<\/span>\r\n}<\/code><\/pre>\n<p>\u53ef\u60dc\u7684\u662f\uff0c\u6211\u6ca1\u80fd\u7ed9\u00a0<code>upgrade_lock<\/code>\u00a0\u627e\u5230\u4e00\u4e2a\u9887\u5177\u5b9e\u9645\u610f\u4e49\u7684\u4f8b\u5b50\u3002<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u539f\u6587\u5730\u5740 STL \u548c Boost \u90fd\u63d0\u4f9b<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[],"tags":[119],"class_list":["post-3779","post","type-post","status-publish","format-standard","hentry","tag-03-"],"_links":{"self":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/3779","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/comments?post=3779"}],"version-history":[{"count":0,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/3779\/revisions"}],"wp:attachment":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/media?parent=3779"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/categories?post=3779"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/tags?post=3779"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}