2017-11-26 11 views
-2

私はちょうど私の自己を尋ねます:コードのスレッドのプールを作るとき
私はコードをコンパイルします
コンパイルされたコードは各スレッドのコピーを持っていますか? 「私は何を考えて」コンパイル時に展開したり、実行時に、
それはコンパイル時に、なぜこの次のコードが必要であればスレッドはコンパイル時または実行時に決定されますか?

と私はマクロ機能を使用する場合、スレッドに渡し、
このマクロでありますミューテックス:唯一のメインスレッドは、その後の作業を実行しているスレッドがすでにラムダ関数を作ったの、既に作られたキュー上で動作します
をio_serviceするスレッドの投稿になりますが、ここで

#include <boost/asio.hpp> 
#include <boost/thread.hpp> 
#include <boost/date_time.hpp> 
#include <iostream> 
namespace asio = boost::asio; 
#define PRINT_ARGS(msg) do {\ 
boost::lock_guard<boost::mutex> lg(mtx); \ 
std::cout << '[' << boost::this_thread::get_id() \ 
<< "] " << msg << std::endl; \ 
} while (0) 
int main() { 
asio::io_service service; 
boost::mutex mtx; 

for (int i = 0; i < 20; ++i) { 
service.post([i, &mtx]() { 
PRINT_ARGS("Handler[" << i << "]"); 
boost::this_thread::sleep(
boost::posix_time::seconds(1)); 
}); 
} 

boost::thread_group pool; 
for (int i = 0; i < 4; ++i) { 
pool.create_thread([&service]() { service.run(); }); 
} 
pool.join_all(); 
} 

lock_guardは、coutのクリティカルセクションを作る>>> >私はミューテックスの必要はないと思う?
これは考えている権利ですか?ここで

私はコンパイル時にマクロ展開をシミュレートします

#include <boost/asio.hpp> 
#include <boost/thread.hpp> 
#include <boost/date_time.hpp> 
#include <iostream> 
namespace asio = boost::asio; 


#define PRINT_ARGS(msg) do {\ 
boost::lock_guard<boost::mutex> lg(mtx); \ 
std::cout << '[' << boost::this_thread::get_id() \ 
<< "] " << msg << std::endl; \ 
} while (0) 

int main() { 
asio::io_service service; 
boost::mutex mtx; 

for (int i = 0; i < 20; ++i) { 
service.post([i, &mtx]() { 

//PRINT_ARGS("Handler[" << i << "]");//>>>>>this will be 

do {\\ 
boost::lock_guard<boost::mutex> lg(mtx); \\ 
std::cout << '[' << boost::this_thread::get_id() \\ 
<< "] " << "Handler[" << i << "]" << std::endl; \\ 
} while (0) 

boost::this_thread::sleep(
boost::posix_time::seconds(1)); 
}); 
} 

boost::thread_group pool; 
for (int i = 0; i < 4; ++i) { 
pool.create_thread([&service]() { service.run(); }); 
} 
pool.join_all(); 
} 

をして、プログラムは、次の順序であろう:
1-メインスレッド:io_serviceインスタンス
2-メインスレッドを作る。作りますmutexのインスタンス
3つのメインスレッド:メインスレッドがこの関数オブジェクトをio_serviceの内部キューに追加しているので、このコードを持つ本で定義されているタスク「lambda関数」を投稿するたびに、ループを20回実行する
私の質問は:主スレッドは20個のラムダ関数オブジェクトをキューに追加しますか?この場合、それぞれが特定の値i
を持っていて、新しい4スレッドが動作を開始すると、スレッド関数 "run"に同じブック
この場合、関数オブジェクトを1つずつ削除して実行します。
スレッド1:ラムダ1を削除し、独自のコードで実行します。
スレッド2:ラムダ2を削除します。ユニークなiを持つ独立したインスタンスとして独自のコードで実行します
スレッド3:ラムダ3を削除し、固有のコードでそれを実行して、ユニークなiと別のインスタンスとして実行します
スレッド4:ラムダを削除します4独自のコードで独自のコードとして実行する
スレッド1 againget lambda 5
これは、キューにラムダ関数として20個の関数オブジェクトがあることは私の理解に基づいています。 "ラッパーのsomesortにラップすることができます"したがって、各スレッドは個別のオブジェクトを取るため、ミューテックス「コンパイル後に内部アセンブリコード20個」は必要ありません。

キュー内のタスクが同じシングルコードへの参照にすぎない場合でも、 2つのスレッドがクリティカルなコードに同時にアクセスするのを防ぐためにmutexが必要です
ここにコード・シグネチャがありますか?

答えて

0

マクロは常にコンパイル時に展開されますが、コンパイラにはスレッドの非常に基本的な知識しかありません(主に特定の変数がスレッドローカルであると言うことができます)。

コードは、実際に実行されるオンディスクイメージまたはメモリ内コピーのいずれかに1回しか存在しません。

PRINT_ARGSでmutexをロックすると、各操作のメッセージが別のスレッドによって中断されることなく完全に出力されます。 (そうでなければ、メッセージの印刷を開始し、メッセージを出力している別のスレッドで別の操作が中断され、残りの最初の操作のメッセージが表示されます)。

+0

私は、マクロ名を展開するコードを編集し、mutexがまだキューに置かれているラムダ関数の中にあり、スレッドに与えられた実行関数がラムダ関数ではないことを発見しました。 1つのラムダを表す20個のタスクがある場合はmutexが必要 –

+0

mutexはタスクではなくcoutのために存在すると思いますか? –

+0

はい、mutexは出力が混ざらないようにします。ラムダは周囲のコンテキストからミューテックスを捕捉しているので、実際には1つのミューテックスしか存在しないことを覚えておいてください。 – SoronelHaetir

関連する問題