程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> c++11: <thread>學習,11thread學習

c++11: <thread>學習,11thread學習

編輯:C++入門知識

c++11: <thread>學習,11thread學習


<thread>頭文件中包含thread類與this_thread命名空間,下面逐一介紹。

thread

1. 構造函數

(1)默認構造函數

thread() noexcept;

默認構造函數不執行任何線程,產生線程對象的線程ID為0。

(2)初始化構造函數

template <class Fn, class... Args>

explicit thread (Fn&& fn, Args&&... args);

產生一個thread對象,提供一個joinable的線程並開始執行。joinable的線程在它們被銷毀前需要被joindetach(否則線程資源不會被完全釋放)。

參數介紹:

fn: 指向函數的指針,指向成員函數的指針,或者任何有移動構造函數(?)的對象(例如重載了operator()的類對象,閉包和函數對象)。如果有返回值的話,返回值被丟棄。

arg…: 傳遞給fn的參數。它們的類型必須是可移動構造的(?)。如果fn是成員函數指針的話,第一個參數必須是調用此方法的對象(或者引用/指針)。

(3)拷貝構造函數

thread (const thread&) = delete;

刪除拷貝構造函數(線程對象不能被拷貝)。

(4)移動構造函數

thread (thread&& x) noexcept;

如果x是一個線程的話,生成一個新的線程對象。這個操作不影響原線程運行,只是將線程的擁有者從x變為新對象,此時x不再代表任何線程(移交了控制權)。

參數介紹:

x: 要移動給構造構造函數的另一線程對象。

例子

// constructing threads
#include <iostream>       // std::cout
#include <atomic>         // std::atomic
#include <thread>         // std::thread
#include <vector>         // std::vector

std::atomic<int> global_counter (0);

void increase_global (int n) { for (int i=0; i<n; ++i) ++global_counter; }

void increase_reference (std::atomic<int>& variable, int n) { for (int i=0; i<n; ++i) ++variable; }

struct C : std::atomic<int> {
  C() : std::atomic<int>(0) {}
  void increase_member (int n) { for (int i=0; i<n; ++i) fetch_add(1); }
};

int main ()
{
  std::vector<std::thread> threads;

  std::cout << "increase global counter with 10 threads...\n";
  for (int i=1; i<=10; ++i)
    threads.push_back(std::thread(increase_global,1000));

  std::cout << "increase counter (foo) with 10 threads using reference...\n";
  std::atomic<int> foo(0);
  for (int i=1; i<=10; ++i)
    threads.push_back(std::thread(increase_reference,std::ref(foo),1000));

  std::cout << "increase counter (bar) with 10 threads using member...\n";
  C bar;
  for (int i=1; i<=10; ++i)
    threads.push_back(std::thread(&C::increase_member,std::ref(bar),1000));

  std::cout << "synchronizing all threads...\n";
  for (auto& th : threads) th.join();

  std::cout << "global_counter: " << global_counter << '\n';
  std::cout << "foo: " << foo << '\n';
  std::cout << "bar: " << bar << '\n';

  return 0;
}

顯示結果

increase global counter using 10 threads...
increase counter (foo) with 10 threads using reference...
increase counter (bar) with 10 threads using member...
synchronizing all threads...
global_counter: 10000
foo: 10000
bar: 10000

2. 析構函數

~thread();

如果線程是joinable的,在銷毀時會調用terminate();

3. 成員函數

(1)void detach();

使該線程不再由調用線程的對象所管理(意味著調用線程不用再使用join方法),讓該線程自己獨立的運行。兩個線程均不再阻塞,同步執行。當一個線程結束執行時,回釋放它自己使用的資源。當調用了這個方法後,線程對象變成non-joinable狀態,可以被安全刪除。

例子

#include <iostream>       // std::cout
#include <thread>         // std::thread, std::this_thread::sleep_for
#include <chrono>         // std::chrono::seconds
 
void pause_thread(int n) 
{
  std::this_thread::sleep_for (std::chrono::seconds(n));
  std::cout << "pause of " << n << " seconds ended\n";
}
 
int main() 
{
  std::cout << "Spawning and detaching 3 threads...\n";
  std::thread (pause_thread,1).detach();
  std::thread (pause_thread,2).detach();
  std::thread (pause_thread,3).detach();
  std::cout << "Done spawning threads.\n";

  std::cout << "(the main thread will now pause for 5 seconds)\n";
  // give the detached threads time to finish (but not guaranteed!):
  pause_thread(5);
  return 0;
}

結果

Spawning and detaching 3 threads...
Done spawning threads.
(the main thread will now pause for 5 seconds)
pause of 1 seconds ended
pause of 2 seconds ended
pause of 3 seconds ended
pause of 5 seconds ended

(2)id get_id() const noexcept;

取得線程id

如果線程對象是joinable的,這個方法返回一個唯一的線程id。

如果線程對象不是joinable的,這個方法返回默認構造對象的id(為0)。

(3)void join();

調用這個函數的主線程會被阻塞直到子線程結束,子線程結束後有一些資源通過主線程回收。當調用這個函數之後,子線程對象變成non-joinable狀態,可以安全銷毀。該函數目的是防止主線程在子線程結束前銷毀,導致資源未成功回收。

例子

// example for thread::join
#include <iostream>       // std::cout
#include <thread>         // std::thread, std::this_thread::sleep_for
#include <chrono>         // std::chrono::seconds
 
void pause_thread(int n) 
{
  std::this_thread::sleep_for (std::chrono::seconds(n));
  std::cout << "pause of " << n << " seconds ended\n";
}
 
int main() 
{
  std::cout << "Spawning 3 threads...\n";
  std::thread t1 (pause_thread,1);
  std::thread t2 (pause_thread,2);
  std::thread t3 (pause_thread,3);
  std::cout << "Done spawning threads. Now waiting for them to join:\n";
  t1.join();
  t2.join();
  t3.join();
  std::cout << "All threads joined!\n";

  return 0;
}

結果

Spawning 3 threads...
Done spawning threads. Now waiting for them to join:
pause of 1 seconds ended
pause of 2 seconds ended
pause of 3 seconds ended
All threads joined!

(4)bool joinable() const noexcept;

返回線程的joinable狀態。

如果一個線程對象是作為一個線程執行的它就是joinable的。

當線程是如下情況的時候就不是joinable的

a. 如果是用默認構造函數產生的(未執行)。

b. 如果它曾被作為移動構造函數的參數(x)。

c. 如果它曾被join或者detach過。

(5)native_handle_type native_handle();

返回A value of member type thread::native_handle_type.

待續…

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved