【C++併發與多線程】 11_shared_future、automic

std::shared_future

類模板

template <class T>  shared_future;
template <class R&> shared_future<R&>;   // specialization : T is a reference type (R&)
template <>         shared_future<void>; // specialization : T is void
  • 一個 shared_future 對象行爲相似於 future 對象,除了它能夠被賦值,並且一個以上的 shared_future 能夠在他們的共享狀態結束時共享全部權。它們還被容許一旦準備好就屢次檢索共享狀態下的值。
  • shared_future 對象能夠從 future 對象隱式轉換,也能夠經過 future::share 顯式得到。在這兩種狀況下,原 future 對象自身將失效。
  • 共享狀態的生存期至少要持續到與之關聯的最後一個對象被銷燬爲止。從 shared_future 中獲取值(使用成員函數 get) 不會釋放其對共享狀態的全部權(與 future 不一樣)。所以,若是與 shared_future 對象相關聯,則共享狀態能夠在最初得到它的對象(若是有的話)以後繼續存在。
成員函數 描述
get 當共享狀態就緒時,返回存儲在共享狀態中的值的引用(或引起其異常)
valid 檢查 shared_future 對象是否與共享狀態關聯
wait 等待共享狀態準備就緒
wait_for 等待共享狀態在 rel_time 指定的時間內準備就緒
wait_until 等待共享狀態準備就緒,最多直到abs_time時間點
#include <iostream>
#include <thread>
#include <future>

using namespace::std;

int mythread()
{
    cout << "mythread begin" << endl;

    this_thread::sleep_for(chrono::microseconds(5000));

    cout << "mythread end" << endl;

    return 5;
}

int main()
{
    cout << "main begin" << endl;

    future<int> result = async(launch::async, mythread);
    shared_future<int> result_s = result.share();

    // 等價
    // shared_future<int> result_s = async(launch::async, mythread);

    if (result_s.valid())
    {
        cout << result_s.get() << endl;

        cout << result_s.get() << endl;

        cout << result_s.get() << endl;
    }

    cout << "main end" << endl;

    return 0;
}

輸出:ios

main begin
mythread begin
mythread end
5
5
5
main end

std::atomic 原子操做

類模板

template <class T> struct atomic;
  • 原子操做是指不會被線程調度機制打斷的操做。這種操做一旦開始,就一直運行到結束,中間不會有任何任何上下文切換。
  • 原子操做能夠是一個步驟,也能夠是多個操做步驟,但其順序不可被打亂,也不能夠被切合只執行其中一部分。
  • 將整個操做視做一個總體是原子操做的核心特徵。

編程實驗

  • 非原子操做,不加鎖,效率很高,但沒法獲得正確的結果
  • 非原子操做,加鎖,效率很低,但結果正確
  • 原子操做,效率很高,且結果正確

測試1:非原子操做,無鎖編程

#include <iostream>
#include <thread>

using namespace::std;

int g_sum = 0;

void add()
{
    for (uint32_t i=0; i<10000000; ++i)
        ++g_sum;
}

int main()
{
   auto beginTime = clock();

   thread t1(add);
   thread t2(add);

   t1.join();
   t2.join();

   auto endTime = clock();

   cout << "time consuming  : " << endTime - beginTime << endl;
   cout << "calculated value: " <<  g_sum << endl;

    return 0;
}

輸出:[速度快,結果錯誤]多線程

time consuming  : 47
calculated value: 10856025

測試2:非原子操做,有鎖async

#include <iostream>
#include <thread>
#include <mutex>

using namespace::std;

int g_sum = 0;
mutex g_mutex;

void add()
{
    for (uint32_t i=0; i<10000000; ++i)
    {
        g_mutex.lock();
        ++g_sum;
        g_mutex.unlock();
    }
}

int main()
{
   auto beginTime = clock();

   thread t1(add);
   thread t2(add);

   t1.join();
   t2.join();

   auto endTime = clock();

   cout << "time consuming  : " << endTime - beginTime << endl;
   cout << "calculated value: " <<  g_sum << endl;

    return 0;
}

輸出:[結果正確,速度慢]函數

time consuming  : 571
calculated value: 20000000

測試3:原子操做測試

#include <iostream>
#include <thread>
#include <atomic>

using namespace::std;

atomic<int> g_sum {0};

void add()
{
    for (uint32_t i=0; i<10000000; ++i)
    {
        ++g_sum;
    }
}

int main()
{
   auto beginTime = clock();

   thread t1(add);
   thread t2(add);

   t1.join();
   t2.join();

   auto endTime = clock();

   cout << "time consuming  : " << endTime - beginTime << endl;
   cout << "calculated value: " <<  g_sum << endl;

    return 0;
}

輸出:[速度快,結果正確]ui

time consuming  : 292
calculated value: 20000000

通常用法

  • 用於多線程環境中的訪問標記
  • 用於多線程環境中的訪問統計
#include <iostream>
#include <thread>
#include <atomic>

using namespace::std;

atomic<bool> g_ifEnd {false};

void mythread()
{
    cout << "mythread begin" << endl;

    chrono::microseconds dura(1000);

    while (!g_ifEnd)
    {
        cout << "mythread thread id :" << this_thread::get_id() << endl;

        this_thread::sleep_for(dura);
    }

    cout << "mythread begin" << endl;
}

int main()
{
   cout << "main end" << endl;

   thread t1(mythread);

   this_thread::sleep_for(chrono::microseconds(5000));

   g_ifEnd = true;

   t1.join();

   cout << "main end" << endl;

    return 0;
}

輸出:this

main end
mythread begin
mythread thread id :2
mythread begin
main end
相關文章
相關標籤/搜索