3

どういうわけかこの質問のフォローアップ。std::mutexa によって処理される関数でa を使用してもよいかどうか疑問に思っているだけboost::asio:io_serviceです。ストランドの使用はやや非現実的です。ブーストリファレンスで見つけたものから、大丈夫だと思います。と記載されているので、

非同期完了ハンドラーは、現在 io_service::run() を呼び出しているスレッドからのみ呼び出されます。

したがって、boost によって作成された他のスレッドが干渉してはなりません。私はそれを正しく理解しましたか?

4

4 に答える 4

12

他の人が指摘したようにstd::mutex、他のロック機構はハンドラー内で使用できます。ただし、この 2 つには次のような基本的な違いがあります。

  • 競合状態からリソースを保護するために、ハンドラ内の外部ロック メカニズムが使用されます。
  • Astrandは、ハンドラー間の競​​合を除去するために使用され、ハンドラー間の競​​合状態が除去されます。

潜在的な競合状態の結果として、スレッドプールの外部のスレッドではなく、他のハンドラーとの潜在的な競合状態の結果としてハンドラー全体が同期されている場合、外部メカニズムとboost::asio::strand.

次のシナリオを検討してください。

  • 2 スレッドのスレッドプールは Boost.Asio で実装されています。
  • ハンドラAB同じミューテックスで同期されます。
  • ハンドラーCは同期を必要としません。
  • ハンドラAB、およびCは にポストされますio_service

AB呼び出されます。両方のスレッドが使用されているため、外部同期が原因でスレッドプールが使い果たされています。残念ながら、スレッドの 1 つがリソースでブロックされているため、同期を必要としないハンドラー ( など)Cがキューに留まります。

このシナリオでストランドが同期に使用される場合、このインスタンスの飢餓は発生しませんでした。strandは独自のハンドラ キューを維持し、そのハンドラの 1 つだけが にあることを保証します。その結果io_service、ハンドラは に配置される前に同期されますio_service。このシナリオでは、ABが に転記された場合strand、は にstrand転記さAio_serviceます。これにより、ACのキューに留まり、が完了するのを待っている間に同時に実行io_serviceできるようになります。CBstrandA

また、これら両方の形式の同期を一緒に使用できるユース ケースもあります。たとえば、リソースがスレッドプールの外部で実行されているスレッドと共有されている場合を考えてみましょう。スレッドプールの内部および外部のスレッドには、依然としてミューテックスが必要です。ただし、astrandを使用して、スレッドプール内部のスレッド間のミューテックスの競合を取り除くことができます。

于 2013-01-14T14:59:53.517 に答える
8

はい、std::mutexハンドラーの内部を使用することはまったく問題ありません。strand結局のところ、Aはミューテックスが偽装された単なるキューです。

于 2013-01-14T01:44:40.163 に答える
2

boost単にその観点からコールバックを呼び出すことです。このコールバックはとは関係がないboostためboost、コールバックで何をするかは関係ありません。したがって、(必要なロックライブラリを使用して)ロックを取得することはまったく問題ありません。

于 2013-01-14T01:45:38.040 に答える
0

完了ハンドラー内のミューテックスは、スレッドの実行をブロックできます。その場合、CPU を 100% ロードするよりも多くのio_serviceスレッドが必要になります。boost::thread::hardware_concurrency()スレッド切り替えのオーバーヘッドが増加します。

于 2014-03-28T01:44:09.130 に答える