C++——マルチスレッドプログラミング(一)std::thread
30077 ワード
(一)C++11マルチスレッドに関するヘッダファイル
C++11の新しい規格には、、、、とです.•:このヘッダには主に2つのクラスが宣言されています.std::atomicとstd::atomic_flagはまた、Cスタイルの原子タイプとCと互換性のある原子操作の関数を宣言した.•:このヘッダファイルは主にstd::threadクラスを宣言し、std::this_threadネーミングスペースもこのヘッダファイルにあります.•:ヘッダファイルは、std::mutexシリーズクラス、std::lock_を含む反発量(mutex)に関連するクラスを主に宣言します.guard, std::unique_lock、その他のタイプと関数.•:このヘッダファイルは、std::condition_を含む条件変数に関連するクラスを主に宣言します.variableとstd::condition_variable_any. •< future>:このヘッダファイルは主にstd::promise,std::package_を宣言しています.taskの2つのProviderクラスとstd::futureとstd::shared_futureの2つのFutureクラスには、関連するタイプと関数もあります.std::async()関数はこのヘッダファイルに宣言されます.
(二)std::thread
0
0.1スレッドステータス
1つのスレッドの生存期間では、複数のステータス間で変換できます.異なるオペレーティングシステムは、異なるスレッドモデルを実現し、多くの異なるスレッドステータスを定義し、各ステータスに複数のサブステータスを含めることができますが、一般的には、次のいくつかのステータスが共通しています.
1)準備完了:スケジューリングに参加し、実行されるのを待つ.スケジューリングが選択されると、直ちに実行を開始する.
2)運転:CPU占有、運転中
3)スリープ:スケジュールに参加せず、特定のイベントの発生を待つ
4)中止:実行済み、スレッドリソースの回収待ち
0.2スレッド環境
スレッドはプロセスに存在し、プロセス内のすべてのグローバルリソースは内部の各スレッドに対して表示されます.
プロセス内の典型的なグローバルリソースは次のとおりです.
1)コード領域:これは、現在のプロセス空間内のすべての可視関数コードを意味し、各スレッドに対しても可視である
2)静的記憶領域:グローバル変数、静的空間
3)ダイナミックストレージエリア:ヒープスペース
スレッド内のローカルリソース:
1)ローカルスタックスペース:このスレッドを格納する関数呼び出しスタック、関数内部のローカル変数など
2)部分レジスタ変数:スレッドの次の実行コードのポインタオフセット量
1構築、割り当て、コピー
1.1コンストラクタ
(1)default :thread() noexcept; (2)initialization :template < class Fn, class… Args> explicit thread (Fn&& fn, Args&&… args); (3)copy [deleted] :thread (const thread&) = delete; (4)move :thread (thread&& x) noexcept;デフォルトのコンストラクション関数は、空のthread実行オブジェクトを作成します. コンストラクション関数を初期化し、joinableによって新しいスレッドがfn関数を呼び出し、argsによって与えられるthreadオブジェクトを作成します. コピーコンストラクション関数(無効)は、threadがコピーコンストラクションされてはいけないことを意味する. moveコンストラクション関数は、呼び出しに成功した後、xはthread実行オブジェクトを表すものではありません.
注意:joinable可能なthreadオブジェクトは、破棄する前にプライマリスレッドjoinまたはdetachedに設定する必要があります.
栗:
注意:std::refについては参照してくださいhttp://tieba.baidu.com/p/1292003201、https://zhidao.baidu.com/question/1240776856100751219.html
Possible output:
1.2 MOVE割付操作
move (1):thread& operator= (thread&& rhs) noexcept; copy [deleted] (2):thread& operator= (const thread&) = delete; move付与操作、現在のオブジェクトがjoinableでない場合、move付与操作に右値参照(rhs)を渡す必要があります.現在のオブジェクトがjoinableである場合、terminate()はエラーを報告します.注意:右の値の参照については、記事を参照してください.http://www.ibm.com/developerworks/cn/aix/library/1307_lisl_c11/ コピー付与操作は無効になり、threadオブジェクトはコピーできません.
注意:C++11のforループ文http://blog.csdn.net/hackmind/article/details/24271949
2その他のメンバー関数
2.1 get_id:スレッドIDを取得します.
パラメータ:none戻り値:An object of member type thread::id that uniquely identifies the thread(if joinable)、or default-constructed(if not joinable)
Returns the thread id.
If the thread object is joinable, the function returns a value that uniquely identifies the thread.
If the thread object is not joinable, the function returns a default-constructed object of member type thread::id.
栗:
output:
2.2 joinable:スレッドがjoinされるかどうかを確認します.
戻り値:false、trueパラメータ:none
Returns whether the thread object is joinable.
A thread object is joinable if it represents a thread of execution.
A thread object is not joinable in any of these cases: •if it was default-constructed. •if it has been moved from (either constructing another thread object, or assigning to it). •if either of its members join or detach has been called.
栗:
Output (after 3 seconds):
2.3 join:Joinスレッド.
パラメータ:none戻り値:none
The function returns when the thread execution has completed.
スレッド関数が実行されるまでjoinは返されません.This synchronizes the moment this function returns with the completion of all the operations in the thread: This blocks the execution of the thread that calls this function until the function called on construction returns (if it hasn’t yet).
After a call to this function, the thread object becomes non-joinable and can be destroyed safely.
栗:
Output (after 3 seconds):
2.4 detach:Detachスレッド
パラメータ:none戻り値:none
Detaches the thread represented by the object from the calling thread, allowing them to execute independently from each other.
Both threads continue without blocking nor synchronizing in any way. Note that when either one ends execution, its resources are released.
After a call to this function, the thread object becomes non-joinable and can be destroyed safely.
栗:
Output (after 5 seconds):
detach呼び出し後、ターゲットスレッドはデーモンスレッドとなり、バックグラウンドで実行され、それに関連付けられたstd::threadオブジェクトはターゲットスレッドへの関連を失い、std::threadオブジェクトによってそのスレッドの制御権を取得できなくなる.スレッドのメイン関数が実行されると、スレッドは終了し、実行時にライブラリはスレッドに関連するリソースをクリーンアップします.
1つのthreadオブジェクトがライフサイクルの終点に達し、関連スレッドがまだ終了していない場合、threadオブジェクトはスレッドとの関連を解除し、ターゲットスレッドは分離スレッドになって検索を続行します.
join関数が呼び出されると、呼び出しスレッドはターゲットスレッドの終了を待機し、ターゲットスレッドのリソースを回収します.
2.5 swap:Swapスレッド.
パラメータ:the thread to swap with戻り値:none
Exchanges the underlying handles of two thread objects
くり
Possible output:
また、void std::swap(thread&lhs,thread&rhs);説明:メンバー関数ではありません.std::swap関数を再ロードしただけです.使用法:std::swap(thread 1,thread 2);栗:
出力:
2.6 native_handle:native handleを返します.
2.7 hardware_concurrency[static]:ハードウェアの同時特性を検出します.
2.8まとめ
http://en.cppreference.com/w/cpp/thread/thread
C++11の新しい規格には、
(二)std::thread
0
0.1スレッドステータス
1つのスレッドの生存期間では、複数のステータス間で変換できます.異なるオペレーティングシステムは、異なるスレッドモデルを実現し、多くの異なるスレッドステータスを定義し、各ステータスに複数のサブステータスを含めることができますが、一般的には、次のいくつかのステータスが共通しています.
1)準備完了:スケジューリングに参加し、実行されるのを待つ.スケジューリングが選択されると、直ちに実行を開始する.
2)運転:CPU占有、運転中
3)スリープ:スケジュールに参加せず、特定のイベントの発生を待つ
4)中止:実行済み、スレッドリソースの回収待ち
0.2スレッド環境
スレッドはプロセスに存在し、プロセス内のすべてのグローバルリソースは内部の各スレッドに対して表示されます.
プロセス内の典型的なグローバルリソースは次のとおりです.
1)コード領域:これは、現在のプロセス空間内のすべての可視関数コードを意味し、各スレッドに対しても可視である
2)静的記憶領域:グローバル変数、静的空間
3)ダイナミックストレージエリア:ヒープスペース
スレッド内のローカルリソース:
1)ローカルスタックスペース:このスレッドを格納する関数呼び出しスタック、関数内部のローカル変数など
2)部分レジスタ変数:スレッドの次の実行コードのポインタオフセット量
1構築、割り当て、コピー
1.1コンストラクタ
(1)default :thread() noexcept; (2)initialization :template < class Fn, class… Args> explicit thread (Fn&& fn, Args&&… args); (3)copy [deleted] :thread (const thread&) = delete; (4)move :thread (thread&& x) noexcept;
注意:joinable可能なthreadオブジェクトは、破棄する前にプライマリスレッドjoinまたはdetachedに設定する必要があります.
栗:
#include
#include
#include
#include
#include
#include
void f1(int n)
{
for (int i = 0; i < 5; ++i)
{
std::cout << "Thread " << n << " executing
";
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void f2(int& n)
{
for (int i = 0; i < 5; ++i) {
std::cout << "Thread 2 executing
";
++n;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
int main()
{
int n = 0;
std::thread t1; // t1 is not a thread
std::thread t2(f1, n + 1); // pass by value
std::thread t3(f2, std::ref(n)); // pass by reference
std::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a thread
t2.join();
t4.join();
std::cout << "Final value of n is " << n << '
';
}
注意:std::refについては参照してくださいhttp://tieba.baidu.com/p/1292003201、https://zhidao.baidu.com/question/1240776856100751219.html
Possible output:
Thread 1 executing
Thread 2 executing
Thread 1 executing
Thread 2 executing
Thread 1 executing
Thread 2 executing
Thread 1 executing
Thread 2 executing
Thread 2 executing
Thread 1 executing
Final value of n is 5
1.2 MOVE割付操作
move (1):thread& operator= (thread&& rhs) noexcept; copy [deleted] (2):thread& operator= (const thread&) = delete;
//#include
//#include
#include // std::chrono::seconds
#include // std::cout
#include // std::thread, std::this_thread::sleep_for
void thread_task(int n) {
std::this_thread::sleep_for(std::chrono::seconds(n));
std::cout << "hello thread "
<< std::this_thread::get_id()
<< " paused " << n << " seconds" << std::endl;
}
/*
* === FUNCTION =========================================================
* Name: main
* Description: program entry routine.
* ========================================================================
*/
int main(int argc, const char *argv[])
{
std::thread threads[5];
std::cout << "Spawning 5 threads...
";
for (int i = 0; i < 5; i++) {
threads[i] = std::thread(thread_task, i + 1); /******copy********/
}
std::cout << "Done spawning threads! Now wait for them to join
";
for (auto& t : threads) {
t.join();
}
std::cout << "All threads joined.
";
system("pause");
return EXIT_SUCCESS;
} /* ---------- end of function main ---------- */
注意:C++11のforループ文http://blog.csdn.net/hackmind/article/details/24271949
2その他のメンバー関数
2.1 get_id:スレッドIDを取得します.
パラメータ:none戻り値:An object of member type thread::id that uniquely identifies the thread(if joinable)、or default-constructed(if not joinable)
Returns the thread id.
If the thread object is joinable, the function returns a value that uniquely identifies the thread.
If the thread object is not joinable, the function returns a default-constructed object of member type thread::id.
栗:
// thread::get_id / this_thread::get_id
#include // std::cout
#include // std::thread, std::thread::id, std::this_thread::get_id
#include // std::chrono::seconds
std::thread::id main_thread_id = std::this_thread::get_id();
void is_main_thread() {
if ( main_thread_id == std::this_thread::get_id() )
std::cout << "This is the main thread.
";
else
std::cout << "This is not the main thread.
";
}
int main()
{
is_main_thread();
std::thread th (is_main_thread);
th.join();
}
output:
This is the main thread.
This is not the main thread.
2.2 joinable:スレッドがjoinされるかどうかを確認します.
戻り値:false、trueパラメータ:none
Returns whether the thread object is joinable.
A thread object is joinable if it represents a thread of execution.
A thread object is not joinable in any of these cases: •if it was default-constructed. •if it has been moved from (either constructing another thread object, or assigning to it). •if either of its members join or detach has been called.
栗:
// example for thread::joinable
#include // std::cout
#include // std::thread
void mythread()
{
// do stuff...
}
int main()
{
std::thread foo;
std::thread bar(mythread);
std::cout << "Joinable after construction:
" << std::boolalpha;
std::cout << "foo: " << foo.joinable() << '
';
std::cout << "bar: " << bar.joinable() << '
';
if (foo.joinable()) foo.join();
if (bar.joinable()) bar.join();
std::cout << "Joinable after joining:
" << std::boolalpha;
std::cout << "foo: " << foo.joinable() << '
';
std::cout << "bar: " << bar.joinable() << '
';
return 0;
}
Output (after 3 seconds):
Joinable after construction:
foo: false
bar: true
Joinable after joining:
foo: false
bar: false
2.3 join:Joinスレッド.
パラメータ:none戻り値:none
The function returns when the thread execution has completed.
スレッド関数が実行されるまでjoinは返されません.This synchronizes the moment this function returns with the completion of all the operations in the thread: This blocks the execution of the thread that calls this function until the function called on construction returns (if it hasn’t yet).
After a call to this function, the thread object becomes non-joinable and can be destroyed safely.
栗:
// example for thread::join
#include // std::cout
#include // std::thread, std::this_thread::sleep_for
#include // std::chrono::seconds
void pause_thread(int n)
{
std::this_thread::sleep_for (std::chrono::seconds(n));
std::cout << "pause of " << n << " seconds ended
";
}
int main()
{
std::cout << "Spawning 3 threads...
";
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:
";
t1.join();
t2.join();
t3.join();
std::cout << "All threads joined!
";
return 0;
}
Output (after 3 seconds):
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!
2.4 detach:Detachスレッド
パラメータ:none戻り値:none
Detaches the thread represented by the object from the calling thread, allowing them to execute independently from each other.
Both threads continue without blocking nor synchronizing in any way. Note that when either one ends execution, its resources are released.
After a call to this function, the thread object becomes non-joinable and can be destroyed safely.
栗:
#include // std::cout
#include // std::thread, std::this_thread::sleep_for
#include // std::chrono::seconds
void pause_thread(int n)
{
std::this_thread::sleep_for (std::chrono::seconds(n));
std::cout << "pause of " << n << " seconds ended
";
}
int main()
{
std::cout << "Spawning and detaching 3 threads...
";
std::thread (pause_thread,1).detach();
std::thread (pause_thread,2).detach();
std::thread (pause_thread,3).detach();
std::cout << "Done spawning threads.
";
std::cout << "(the main thread will now pause for 5 seconds)
";
// give the detached threads time to finish (but not guaranteed!):
pause_thread(5);
return 0;
}
Output (after 5 seconds):
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
detach呼び出し後、ターゲットスレッドはデーモンスレッドとなり、バックグラウンドで実行され、それに関連付けられたstd::threadオブジェクトはターゲットスレッドへの関連を失い、std::threadオブジェクトによってそのスレッドの制御権を取得できなくなる.スレッドのメイン関数が実行されると、スレッドは終了し、実行時にライブラリはスレッドに関連するリソースをクリーンアップします.
1つのthreadオブジェクトがライフサイクルの終点に達し、関連スレッドがまだ終了していない場合、threadオブジェクトはスレッドとの関連を解除し、ターゲットスレッドは分離スレッドになって検索を続行します.
join関数が呼び出されると、呼び出しスレッドはターゲットスレッドの終了を待機し、ターゲットスレッドのリソースを回収します.
2.5 swap:Swapスレッド.
パラメータ:the thread to swap with戻り値:none
Exchanges the underlying handles of two thread objects
くり
#include
#include
#include
void foo()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
void bar()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main()
{
std::thread t1(foo);
std::thread t2(bar);
std::cout << "thread 1 id: " << t1.get_id() << std::endl;
std::cout << "thread 2 id: " << t2.get_id() << std::endl;
std::swap(t1, t2);
std::cout << "after std::swap(t1, t2):" << std::endl;
std::cout << "thread 1 id: " << t1.get_id() << std::endl;
std::cout << "thread 2 id: " << t2.get_id() << std::endl;
t1.swap(t2);
std::cout << "after t1.swap(t2):" << std::endl;
std::cout << "thread 1 id: " << t1.get_id() << std::endl;
std::cout << "thread 2 id: " << t2.get_id() << std::endl;
t1.join();
t2.join();
}
Possible output:
thread 1 id: 1892
thread 2 id: 2584
after std::swap(t1, t2):
thread 1 id: 2584
thread 2 id: 1892
after t1.swap(t2):
thread 1 id: 1892
thread 2 id: 2584
また、void std::swap(thread&lhs,thread&rhs);説明:メンバー関数ではありません.std::swap関数を再ロードしただけです.使用法:std::swap(thread 1,thread 2);栗:
#include
#include
#include
void foo()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
void bar()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main()
{
std::thread t1(foo);
std::thread t2(bar);
std::cout << "thread 1 id: " << t1.get_id() << std::endl;
std::cout << "thread 2 id: " << t2.get_id() << std::endl;
std::swap(t1, t2);
std::cout << "after std::swap(t1, t2):" << std::endl;
std::cout << "thread 1 id: " << t1.get_id() << std::endl;
std::cout << "thread 2 id: " << t2.get_id() << std::endl;
t1.swap(t2);
std::cout << "after t1.swap(t2):" << std::endl;
std::cout << "thread 1 id: " << t1.get_id() << std::endl;
std::cout << "thread 2 id: " << t2.get_id() << std::endl;
t1.join();
t2.join();
}
出力:
thread 1 id: 1892
thread 2 id: 2584
after std::swap(t1, t2):
thread 1 id: 2584
thread 2 id: 1892
after t1.swap(t2):
thread 1 id: 1892
thread 2 id: 2584
2.6 native_handle:native handleを返します.
2.7 hardware_concurrency[static]:ハードウェアの同時特性を検出します.
2.8まとめ
http://en.cppreference.com/w/cpp/thread/thread
std::thread m_thrSend; //
bool m_sending{ false }; //
bool startSend()
{
if (m_sending)
return false;
m_sending = true;
m_thrSend = std::thread([this](){
this->thrSend(); });
return true;
}
void stopSend()
{
m_sending = false;
std::this_thread::sleep_for(std::chrono::milliseconds(50));
if (m_thrSend.joinable())
m_thrSend.join();
}