乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      C++11 并發(fā)指南六(atomic 類型詳解一 atomic

       wtkc 2014-11-20

      C++11 并發(fā)指南已經(jīng)寫了 5 章,前五章重點介紹了多線程編程方面的內(nèi)容,但大部分內(nèi)容只涉及多線程、互斥量、條件變量和異步編程相關(guān)的 API,C++11 程序員完全可以不必知道這些 API 在底層是如何實現(xiàn)的,只需要清楚 C++11 多線程和異步編程相關(guān) API 的語義,然后熟加練習(xí)即可應(yīng)付大部分多線程編碼需求。但是在很多極端的場合下為了性能和效率,我們需要開發(fā)一些 lock-free 的算法和數(shù)據(jù)結(jié)構(gòu),前面幾章的內(nèi)容可能就派不上用場了,因此從本文開始介紹 C++11 標(biāo)準(zhǔn)中 <atomic> 頭文件里面的類和相關(guān)函數(shù)。

      本文介紹 <atomic> 頭文件中最簡單的原子類型: atomic_flag。atomic_flag 一種簡單的原子布爾類型,只支持兩種操作,test-and-set 和 clear。

      std::atomic_flag 構(gòu)造函數(shù)

      std::atomic_flag 構(gòu)造函數(shù)如下:

      • atomic_flag() noexcept = default;
      • atomic_flag (const atomic_flag&T) = delete;

      std::atomic_flag 只有默認(rèn)構(gòu)造函數(shù),拷貝構(gòu)造函數(shù)已被禁用,因此不能從其他的 std::atomic_flag 對象構(gòu)造一個新的 std::atomic_flag 對象。

      如果在初始化時沒有明確使用 ATOMIC_FLAG_INIT初始化,那么新創(chuàng)建的 std::atomic_flag 對象的狀態(tài)是未指定的(unspecified)(既沒有被 set 也沒有被 clear。)另外,atomic_flag不能被拷貝,也不能 move 賦值。

      ATOMIC_FLAG_INIT: 如果某個 std::atomic_flag 對象使用該宏初始化,那么可以保證該 std::atomic_flag 對象在創(chuàng)建時處于 clear 狀態(tài)。

      下面先看一個簡單的例子,main() 函數(shù)中創(chuàng)建了 10 個線程進(jìn)行計數(shù),率先完成計數(shù)任務(wù)的線程輸出自己的 ID,后續(xù)完成計數(shù)任務(wù)的線程不會輸出自身 ID:

      復(fù)制代碼
      #include <iostream>              // std::cout
      #include <atomic>                // std::atomic, std::atomic_flag, ATOMIC_FLAG_INIT
      #include <thread>                // std::thread, std::this_thread::yield
      #include <vector>                // std::vector
      
      std::atomic<bool> ready(false);    // can be checked without being set
      std::atomic_flag winner = ATOMIC_FLAG_INIT;    // always set when checked
      
      void count1m(int id)
      {
          while (!ready) {
              std::this_thread::yield();
          } // 等待主線程中設(shè)置 ready 為 true.
      
          for (int i = 0; i < 1000000; ++i) {
          } // 計數(shù).
      
          // 如果某個線程率先執(zhí)行完上面的計數(shù)過程,則輸出自己的 ID.
          // 此后其他線程執(zhí)行 test_and_set 是 if 語句判斷為 false,
          // 因此不會輸出自身 ID.
          if (!winner.test_and_set()) {
              std::cout << "thread #" << id << " won!\n";
          }
      };
      
      int main()
      {
          std::vector<std::thread> threads;
          std::cout << "spawning 10 threads that count to 1 million...\n";
          for (int i = 1; i <= 10; ++i)
              threads.push_back(std::thread(count1m, i));
          ready = true;
      
          for (auto & th:threads)
              th.join();
      
          return 0;
      }
      復(fù)制代碼

      多次執(zhí)行結(jié)果如下:

      復(fù)制代碼
      atomic ) ./Atomic-Flag1 
      spawning 10 threads that count to 1 million...
      thread #6 won!
      atomic ) ./Atomic-Flag1 
      spawning 10 threads that count to 1 million...
      thread #1 won!
      atomic ) ./Atomic-Flag1 
      spawning 10 threads that count to 1 million...
      thread #5 won!
      atomic ) ./Atomic-Flag1 
      spawning 10 threads that count to 1 million...
      thread #1 won!
      atomic ) ./Atomic-Flag1 
      spawning 10 threads that count to 1 million...
      thread #1 won!
      atomic ) ./Atomic-Flag1 
      spawning 10 threads that count to 1 million...
      thread #10 won!
      復(fù)制代碼

      std::atomic_flag::test_and_set 介紹

      std::atomic_flag 的 test_and_set 函數(shù)原型如下:

      bool test_and_set (memory_order sync = memory_order_seq_cst) volatile noexcept;
      bool test_and_set (memory_order sync = memory_order_seq_cst) noexcept;

      test_and_set() 函數(shù)檢查 std::atomic_flag 標(biāo)志,如果 std::atomic_flag 之前沒有被設(shè)置過,則設(shè)置 std::atomic_flag 的標(biāo)志,并返回先前該 std::atomic_flag 對象是否被設(shè)置過,如果之前 std::atomic_flag 對象已被設(shè)置,則返回 true,否則返回 false。

      test-and-set 操作是原子的(因此 test-and-set 是原子 read-modify-write (RMW)操作)。

      test_and_set 可以指定 Memory Order(后續(xù)的文章會詳細(xì)介紹 C++11 的 Memory Order,此處為了完整性列出 test_and_set 參數(shù) sync 的取值),取值如下:

       

      Memory Order 值Memory Order 類型
      memory_order_relaxed Relaxed
      memory_order_consume Consume
      memory_order_acquire Acquire
      memory_order_release Release
      memory_order_acq_rel Acquire/Release
      memory_order_seq_cst Sequentially consistent

       一個簡單的例子:

      復(fù)制代碼
      #include <iostream>                // std::cout
      #include <atomic>                // std::atomic_flag
      #include <thread>                // std::thread
      #include <vector>                // std::vector
      #include <sstream>                // std::stringstream
      
      std::atomic_flag lock_stream = ATOMIC_FLAG_INIT;
      std::stringstream stream;
      
      void append_number(int x)
      {
          while (lock_stream.test_and_set()) {
          }
          stream << "thread #" << x << '\n';
          lock_stream.clear();
      }
      
      int main()
      {
          std::vector < std::thread > threads;
          for (int i = 1; i <= 10; ++i)
              threads.push_back(std::thread(append_number, i));
          for (auto & th:threads)
              th.join();
      
          std::cout << stream.str() << std::endl;;
          return 0;
      }
      復(fù)制代碼

      執(zhí)行結(jié)果如下:

      復(fù)制代碼
      thread #1
      thread #2
      thread #3
      thread #4
      thread #5
      thread #6
      thread #7
      thread #8
      thread #9
      thread #10
      復(fù)制代碼

      std::atomic_flag::clear() 介紹

      清除 std::atomic_flag 對象的標(biāo)志位,即設(shè)置 atomic_flag 的值為 false。clear 函數(shù)原型如下:

      void clear (memory_order sync = memory_order_seq_cst) volatile noexcept;
      void clear (memory_order sync = memory_order_seq_cst) noexcept;

      清除 std::atomic_flag 標(biāo)志使得下一次調(diào)用 std::atomic_flag::test_and_set 返回 false。

      std::atomic_flag::clear() 可以指定 Memory Order(后續(xù)的文章會詳細(xì)介紹 C++11 的 Memory Order,此處為了完整性列出 clear 參數(shù) sync 的取值),取值如下:

       

      Memory Order 值Memory Order 類型
      memory_order_relaxed Relaxed
      memory_order_consume Consume
      memory_order_acquire Acquire
      memory_order_release Release
      memory_order_acq_rel Acquire/Release
      memory_order_seq_cst Sequentially consistent

      結(jié)合 std::atomic_flag::test_and_set() 和 std::atomic_flag::clear(),std::atomic_flag 對象可以當(dāng)作一個簡單的自旋鎖使用,請看下例:

      復(fù)制代碼
      #include <thread>
      #include <vector>
      #include <iostream>
      #include <atomic>
      
      std::atomic_flag lock = ATOMIC_FLAG_INIT;
      
      void f(int n)
      {
          for (int cnt = 0; cnt < 100; ++cnt) {
              while (lock.test_and_set(std::memory_order_acquire))  // acquire lock
                   ; // spin
              std::cout << "Output from thread " << n << '\n';
              lock.clear(std::memory_order_release);               // release lock
          }
      }
      
      int main()
      {
          std::vector<std::thread> v;
          for (int n = 0; n < 10; ++n) {
              v.emplace_back(f, n);
          }
          for (auto& t : v) {
              t.join();
          }
      }
      復(fù)制代碼

      在上面的程序中,std::atomic_flag 對象 lock 的上鎖操作可以理解為 lock.test_and_set(std::memory_order_acquire); (此處指定了 Memory Order,更多有關(guān) Memory Order 的概念,我會在后續(xù)的文章中介紹),解鎖操作相當(dāng)與 lock.clear(std::memory_order_release)。

      在上鎖的時候,如果 lock.test_and_set 返回 false,則表示上鎖成功(此時 while 不會進(jìn)入自旋狀態(tài)),因為此前 lock 的標(biāo)志位為 false(即沒有線程對 lock 進(jìn)行上鎖操作),但調(diào)用 test_and_set 后 lock 的標(biāo)志位為 true,說明某一線程已經(jīng)成功獲得了 lock 鎖。

      如果在該線程解鎖(即調(diào)用 lock.clear(std::memory_order_release)) 之前,另外一個線程也調(diào)用 lock.test_and_set(std::memory_order_acquire) 試圖獲得鎖,則 test_and_set(std::memory_order_acquire) 返回 true,則 while 進(jìn)入自旋狀態(tài)。如果獲得鎖的線程解鎖(即調(diào)用了 lock.clear(std::memory_order_release))之后,某個線程試圖調(diào)用 lock.test_and_set(std::memory_order_acquire) 并且返回 false,則 while 不會進(jìn)入自旋,此時表明該線程成功地獲得了鎖。

      按照上面的分析,我們知道在某種情況下 std::atomic_flag 對象可以當(dāng)作一個簡單的自旋鎖使用。

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多