他の人が指摘したようにstd::mutex、他のロック機構はハンドラー内で使用できます。ただし、この 2 つには次のような基本的な違いがあります。
- 競合状態からリソースを保護するために、ハンドラ内の外部ロック メカニズムが使用されます。
- A
strandは、ハンドラー間の競合を除去するために使用され、ハンドラー間の競合状態が除去されます。
潜在的な競合状態の結果として、スレッドプールの外部のスレッドではなく、他のハンドラーとの潜在的な競合状態の結果としてハンドラー全体が同期されている場合、外部メカニズムとboost::asio::strand.
次のシナリオを検討してください。
- 2 スレッドのスレッドプールは Boost.Asio で実装されています。
- ハンドラ
AとB同じミューテックスで同期されます。
- ハンドラー
Cは同期を必要としません。
- ハンドラ
A、B、およびCは にポストされますio_service。
AとB呼び出されます。両方のスレッドが使用されているため、外部同期が原因でスレッドプールが使い果たされています。残念ながら、スレッドの 1 つがリソースでブロックされているため、同期を必要としないハンドラー ( など)Cがキューに留まります。
このシナリオでストランドが同期に使用される場合、このインスタンスの飢餓は発生しませんでした。strandは独自のハンドラ キューを維持し、そのハンドラの 1 つだけが にあることを保証します。その結果io_service、ハンドラは に配置される前に同期されますio_service。このシナリオでは、AとBが に転記された場合strand、は にstrand転記さAれio_serviceます。これにより、AがCのキューに留まり、が完了するのを待っている間に同時に実行io_serviceできるようになります。CBstrandA
また、これら両方の形式の同期を一緒に使用できるユース ケースもあります。たとえば、リソースがスレッドプールの外部で実行されているスレッドと共有されている場合を考えてみましょう。スレッドプールの内部および外部のスレッドには、依然としてミューテックスが必要です。ただし、astrandを使用して、スレッドプール内部のスレッド間のミューテックスの競合を取り除くことができます。