2017-01-02 2 views
2

は、このコード(Simple-Web-Serverから抽出されたが、ライブラリーの知識は、この質問に答えるために必要はありません)考えてみましょう:メモリフェンスはここに必要ですか?

HttpServer server; 
thread server_thread; 

server.config.port = 8080; 
server.default_resource["GET"] = [](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) { 
    string content = "Hello world!" 
    *response << "HTTP/1.1 200 OK\r\nContent-Length: " << content.size() << "\r\n\r\n" << content; 
}; 

server_thread = thread([&server]() { 
    server.start(); 
}); 

HttpServer::default_resourceのstd :: unordered_mapで、私の理解には、されていません、スレッドセーフです。 portは符号なしのshortです。メインスレッドが他のスレッドからアクセス可能なメモリにportdefault_resourceへの変更を書かれていない可能性がありますよう

新しいスレッドで見られるように、C++のメモリフェンスの私の理解は、server正しいと仮定すると、有効な状態ではない可能性があります。そのため、server.start()が正しく動作しない可能性があります。

HttpServer server; 
thread server_thread; 

server.config.port = 8080; 
server.default_resource["GET"] = [](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) { 
    string content = "Hello world!" 
    *response << "HTTP/1.1 200 OK\r\nContent-Length: " << content.size() << "\r\n\r\n" << content; 
}; 

atomic_thread_fence(memory_order_release); 

server_thread = thread([&server]() { 
    atomic_thread_fence(memory_order_acquire); 
    server.start(); 
}); 

が私の理解は正しいです、そして両方atomic_thread_fence秒必要です。この問題を解決するには

、私はatomic_thread_fence秒に追加することで、コードを変更する必要がありますか?

+3

スレッドの初期化前に親スレッドによって実行されるすべての操作は、作成されたばかりのスレッドの観点から完了している必要があります。したがってこの場合、サーバが 'std :: thread :: thread()'の呼び出しの前に初期化されているので、スレッドフェンスは必要ありません。 –

+0

スレッドハンドラオブジェクト(C++オブジェクト)と実際のスレッド(同時実行のコンセプト)を混同しているようです。 –

答えて

5

30.3.1.2スレッドコンストラクタ

template <class F, class ...Args> 
explicit thread(F&& f, Args&&... args); 

同期:fのコピーの呼び出しの開始と同期 コンストラクタの呼び出しが完了しました。

つまり、スレッド関数が呼び出されると、親スレッドで発生したすべてのものと同期されます(std::threadが親スレッドで構築されるまで)。

この種の明示的なメモリバリア/フェンスは必要ありません。

+0

OPsコードはむしろ 'server'が引数として渡され、その時点でその変数に影響を与えた副作用を持つすべての前のコードが実行されていなければなりませんか?たとえば、 'server'が引数として渡されず、代わりにグローバルであるとします。正しく理解すれば、同期の問題が発生していたとします。引用されたテキストは、単にスレッドコンストラクタがスレッドコールバックの前に実行されなければならないと言っています。 – Lundin

+0

pthread_create()がstd :: threadの代わりに使用されてもメモリフェンスは必要ありません。経験則は、スレッドを作成するか、mutexやその他の同期プリミティブを使用して別のスレッドを待つことで、暗黙的に必要なフェンスを発行します。あなたはそれを自分で行う必要はありません。残念ながら、私はそれのための証明リンクを提供することはできません。 –

+0

スレッドに参加するときと同じになりますか?つまり、thread :: join()を呼び出した後に明示的なフェンスは必要ありませんか? – Bernard

関連する問題