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