2012-03-05 9 views
2

同期読み取りスレッドから別のスレッドでtcp :: socketを閉じることができますか?私は、TCPのdocumentを見[boost.asio] I/Oスレッドとは別のスレッドでtcp :: socketまたはtcp :: acceptorを閉じる

tcp_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both); 
tcp_socket->close(); 

::ソケット:

boost::asio::ip::tcp::socket* tcp_socket; //blocking mode 

スレッド1:

while(true){ 
    try{ 
     std::vector<char> read_buffer(10); 
     tcp_socket->read_some(boost::asio::buffer(read_buffer)); 
    } 
    catch(boost::system::system_error& e){ 
    //TODO 
    break; 
    } 
} 

スレッド2のように に見えます。彼らは、オブジェクトがスレッド非難的であると言います。しかしデモコードはうまくいくようです。 それは安全ですか? tcp :: acceptorはどうですか?同じtcp :: acceptorで、closeを呼び出してマルチスレッドで受け入れる ?

答えて

4

ドキュメントには、tcp::socketが共有オブジェクトに対してスレッドセーフではないことが記載されています。

一見、それは常に動作することを保証するものではありません。

さらに、ソケットレイヤーで別のスレッドからソケットを閉じることは、ブロックスレッドをブロック解除するポータブルな方法ではありません。

は、ここで私は示唆しているものです:

  • はASIOの非同期APIを使用してください。
  • mutexを使用してソケットを保護して、同時アクセスを防止するか、asioストランドを使用してアクセスをシリアル化します。 similar質問に著者を引用

:実際には実際に

...

は、それはおそらく** ASIO現在 がサポートするプラットフォーム上で動作します。しかし、私は意図的に のようなインターフェイスを指定しました。ではなく、スレッドセーフです。これは、 の実装を明示的に 同期を必要とせずにソケットオブジェクトに追加状態を格納することを可能にするためです。

同じソケットで複数の同時操作を実行する場合は、 安全な移植可能な方法は、非同期操作を使用することです。

**ソケットを非ブロックにしない限り、乾杯、クリス

2

閉じる後に他のスレッドがtcp_socketを使用していないことを保証できる限り、安全です。あなたの例では、thread2がスレッドを閉じようとしている間にスレッド1が読み取りループにまだ入っていれば、競合状態になります。

thread-shared variablesを使用してthread1に信号を送り、ループを終了し、a barrierを使用すると、thread1が安全な状態になった後にソケットが閉じられることを保証できます。

+0

Thanskご返信用

。デモコードを実行します。スレッド1とスレッド2を同期させるロックはありません。tcp_socket-> close()が呼び出された後、thread1は「ファイルの終了」例外をキャッチし、break.Iはこれを合理的な説明とする文書は見つかりませんでした。 – Mamrot

+0

ロックなしで何かが起こる可能性があります。あなたのプラットフォームではおそらく幸運なことですが、それは移植性があるというわけではありません。もう1つの答えが強調されたように、*並行アクセス(つまり、同じオブジェクトに同時にアクセスする2つのスレッド)のようなものは、問題を引き起こします。同時アクセスを禁止すると、スレッド間でオブジェクトを共有することは安全です。 – ComicSansMS

関連する問題