より複雑なプロセス:別のプロセスへの適用は、彼らが同時に実行されます。示されるように、従来のメッセージを送信するプロセス間通信チャネル(信号ソケット、ファイル、パイプ、等)によって別のプロセス。
利点:1.オペレーティング・システムは、操作とプロセス間のより高いレベルの保護付属の追加の通信メカニズムを提供し、あなたがより安全な並行コードを書くことができますを意味します。
2.通信コストの増加にもかかわらず、異なるマシン上の別のプロセスで実行され、リモート接続を使用するが、うまく設計されたシステムの数ができ、これは、可用性および性能平行を改善するために低コストの方法であってもよいです。
短所:このようなプロセスの間に1回の通信は、通常、複雑な設定されていない別のプロセスデータに処理を変更しないように、オペレーティングシステムは、プロセス間のある程度の保護を提供するので、遅いです
複数のプロセスを実行するために必要な2.固定オーバーヘッド:プロセスを開始するために必要な時間は、オペレーティング・システムは、内部リソースのプロセスを管理する必要があります
マルチスレッド:単一のプロセスで複数のスレッドを実行します。各スレッドは独立して実行すると、スレッドが異なる命令シーケンス上で実行することができます:スレッドは軽量プロセスです。しかし、プロセス内のすべてのスレッドは、アドレス空間を共有し、すべてのスレッドによってアクセスされるデータのほとんど---グローバル変数はまだグローバル、オブジェクト・リファレンス・ポインタであるか、またはデータがスレッド間で渡すことができます。
長所:オペレーティング・システムのワークロードの記録が小さくなるように、このアドレス空間は、高価な、とスレッド間のデータの保護の欠如だったので、マルチスレッドのオーバーヘッドを使用すると、複数のプロセスを使用するよりもはるかに小さいです
短所:柔軟性、コスト共有メモリ:データは複数のスレッドによってアクセスされる場合、プログラマは、データへの各スレッドのアクセスを大切にしなければならない作業の多くは、スレッド間で通信するために行われる必要があることを意味する、と同じです
並行並列:
並列パフォーマンスにもっと注意を払います。高速大容量のデータ処理を改善するために、現在利用可能なハードウェアの使用を議論では、我々は、プログラムの並列性を議論する。焦点が反応して別のタスクまたはタスクであるとき、同時実行のプログラムについて説明します
std ::スレッド学習
ヘッダファイルは<スレッド>を含む必要があります
スレッドを初期化(スレッドを開始)
簡単な例:
書式#include <iostreamの> の#include <スレッド> 使用して名前空間はstdを、無効のsayHello() { COUT << " ハロー" << ENDLと、 } int型のmain() { スレッドT(のsayHello)。 t.join(); }
std ::スレッド(FUNC):スレッド(スレッド開始)を初期化することはstd ::スレッドのインスタンスを構築することです。機能アプリケーションの種類、以下の実施例は、単純な手段関数func:
書式#include <iostreamの> の#include <スレッド> 使用して名前空間はstdを、クラステスト { 公共: ボイド演算子()() { COUT << " ハロー" << ENDL。 } }。INT メイン() { テストテスト。 スレッドT(試験)。 t.join(); }
std ::スレッド(&クラス:: funcを、(クラス)のオブジェクト):あなたはまたのstd ::スレッドを初期化するために、クラスのメンバ変数を使用することができます
書式#include <iostreamの> の#include <スレッド> 使用して名前空間はstdを、クラステスト { 公共: ボイドのsayHello() { COUT << " ハロー" << ENDL。 } }。INT メイン() { テストテスト。 スレッドT( &テスト::のsayHello、&テスト)。 t.join(); }
注意:関数オブジェクトがスレッドコンストラクタに渡されると、次のような状況を回避する必要性:変数を渡す場合は、代わりの名前、C ++コンパイラの一時変数ではなくオブジェクトのタイプよりも、関数宣言と解釈定義。例えば:
std ::スレッドmyThread(FUNC());
ここで、この関数は、関数ではなく、スレッドの開始、のstd ::スレッドオブジェクトを返す、(パラメータなしで関数へのポインタと関数funcオブジェクトを返し)つのパラメータをとり、myThread呼び出される関数を宣言することと等価です。
この問題を解決するために、解決策:
- 括弧の複数のセットを使用します
std ::スレッドmyThread((FUNC()));
- 中括弧を使用してください
std ::スレッドmyThread({FUNC()})。
- ラムダ式を使用します
STD :: myThread([](){スレッド
do_somethingを();
});
スレッドを開始した後、決定を行うためにない場合は、オブジェクトが破壊される前に、プログラムは(デストラクタのはstd ::スレッドを終了し、スレッド(スタイルへの参加)の終了を待つか、自律的に(別の)動作させるための明確な必要性がありますコールのstd ::終了())。異常な状況であるだけでなく、正しいスレッドが参加できることを確認する(結合)または分離していても(デタッチ)。
あなたがスレッドを待たない場合は、スレッドの終了前に実効性を確保する必要がある、あなたはデータにアクセスすることができます。例えば、子スレッドのメインスレッドは、変数A、サブスレッドデタッチへの参照を渡し、それはメインスレッドは、変数Aが破壊されるように、子スレッド、子スレッド前に終了した後、参照を使用することができることを意味生成します例外。このような状況に対処する従来の方法:スレッド関数は、スレッドにデータをコピーし、完了した共有データにコピーされません。あなたがスレッド関数として呼び出し可能なオブジェクトを使用している場合、このオブジェクトはスレッドにコピーされ、その後、元のオブジェクトはすぐに破棄されますが、オブジェクトはポインタと参照は慎重にする必要が含まれています。ベストのスレッドを作成するために、関数のローカル変数を使用しません。また、関数の前に糸の端部が加わる()関数によって行われることを保証することが可能です。
スレッドが完了するのを待ちます
std ::スレッドメソッドを使用すると、待機中のスレッドの完了を達成するために)(参加します
()の挙動に参加コールするだけでなく、スレッドに関連する記憶部をクリーンアップする、このstd::thread
オブジェクトはもはやスレッドの完了を持つ任意の関連を持ちません。これは一度に一つだけのスレッドが()結合を使用していることを意味し、あなたが()、参加を使用するとstd::thread
)(その使用合流可能で、falseを返したときにオブジェクトを再度追加することはできません。
バックグラウンドスレッドで実行されています
待機中のスレッドの完了を達成するためにはstd ::スレッド方式のデタッチ()を使用
デタッチ()スレッドは、メインスレッドが彼らとの直接的な相互作用を持っていないことを意味し、バックグラウンドで実行されます使用してください。換言すれば、スレッドの終了を待たない、スレッド分離場合、存在することができないstd::thread
オブジェクトのスレッドを分離し、それを参照することができ、実際にバックグラウンドで実行されるので、別のスレッドを追加することができません。、関連リソースを適切にリサイクルすることができたときにスレッドが終了しかし、C ++ランタイムライブラリのことを確認するために、バックグラウンドスレッドのCの所有権および制御++ランタイムライブラリが処理されます。場合std::thread
t.joinableを使用してオブジェクト()がtrueを返し、それは)(t.detachを使用することができます
スレッド関数にパラメータを渡します
スレッドパラメータ渡されたのstd ::スレッド(&クラス:: FUNCを、(初期化するために、クラスのメンバ関数で使用する以外に、初期化パラメータの間に渡されたのstd ::スレッドmyThread(FUNC、arg0は、arg1に、...)を行うことができ、クラス)のオブジェクト、arg0は、arg1に、...)
ここでは、2つの問題に注意が必要です。
1.スレッドへのパラメータとして動的な変数へのポインタは、あなたがに依存したく期待するリテラルに変換するために、暗黙的な変換関数オブジェクト(1)が、
std::thread
コピーコンストラクタは変数を提供します、ただのコピー文字列リテラルの所望の型に変換されません。溶液は、(2)最初の前に表示された着信変換します
空はf(int型 I、のstd :: 文字列 のconst&S)を。 ボイドおっと(int型some_param) { char型バッファ[ 1024 ]。 sprintf(バッファ、" %のI " 、some_param)。 // はstd ::スレッドT(F、3、バッファ); // 1 のstd ::スレッドT(F、3、のstd :: 文字列(緩衝液))。 // 2使用のstd ::文字列、避免悬垂指针 t.detach(); }
2.参照を渡すことが期待が、オブジェクト全体がコピーされます。パラメータの型を渡すことが望ましいが(1)を意味するが、std::thread
コンストラクタを認識していない、変数は、予想されるコピーコンストラクタ関数パラメータのタイプを無視し、ブラインドが提供されています。
溶液は、基準フォームにパラメータを変換する)(STD :: REFを使用することである(2)
ボイド update_data_for_widget(WIDGET_ID W、widget_data&データ)。 ボイドoops_again(WIDGET_ID W) { widget_dataデータ。 // はstd ::スレッドT(update_data_for_widget、データ、W)。// 1つ のstd ::スレッドT(update_data_for_widget、W、STD :: REF (データ))。// 2 display_status()。 t.join(); process_widget_data(データ)。 }
参考文献:
https://chenxiaowei.gitbook.io/c-concurrency-in-action-second-edition-2019/