プロデューサースレッドがnumEmptySpaces
キューへのアクセスをセマフォで待機している場合、セマフォ待機キューをFIFO以外に実装するのは不合理であるため、この動作はおそらく発生しますが、ほとんどのセマフォ実装では保証されません。
「スレッドの順序」の要件を定義するのは難しいため、この種の動作を保証することは非常に厄介です。
どのスレッドが最初に到着したかをどのように定義できますか?
「最初のスレッド」が他のスレッドの進行を妨げる何らかのロックを取得した場合、後続のスレッドは「すぐに」群れになるため、OSによって提供されるロックキューの順序に従います。
私が考えることができる唯一のことは、何かをロック/キューに入れる前に、すべてのプロデューサースレッドにロックフリーのタイムスタンプまたはシーケンス番号を取得させることです。これは、「通常の」アトミックインクリメント命令で実行できます。その後、プロデューサーが「numEmptySpaces」ユニットを取得して「入り」、キューをロックすると、プロデューサーはシーケンス番号順に自分自身をキューにエンキューできます。
これに標準BlockingCollection
を使用できるかどうかはわかりません。シーケンス番号でエントリを「OrderBy」できる場合がありますが、この操作でキューがロックされるかどうかはわかりません。ロックする必要がありますが、..さらに、sequenceNoをBlockingCollectionのプライベートメンバーとして追加する必要があります。子孫とアトミックインクリメントの結果は、各タスクの状態として維持されますTask
。メンバーに追加する必要があります。
BlockingQueue
numEmptySpacesユニットとキューミューテックスが取得されたら、「通常の」キューを使用して独自のクラスでビルドし、セマフォとミューテックスを組み合わせてこれを実装し、新しいタスクをシーケンス番号順にキューに挿入したいと思います。次に、アトミックインクリメントの結果をスタック/自動変数にアセンブルできます。
これはインタビューの質問として正当化されるかもしれませんが、実際に本番コードに実装するには、解雇の脅威にさらされる必要があります。それが不可欠かもしれない状況を考えるのは非常に難しいです。余分なオーバーヘッドと競合の欠点は、私が考えることができるすべての点で疑わしい利点を上回ります。
デキュー/実行の最後に、あらゆる種類の順序を明示的に維持しようとすることについて、同様の予約があります。デキューされたタスクのいくつかの「チェックポイント」がシーケンス番号順に到達したことを確認するのは面倒です。タスクからの協力が必要であり、チェックポイントに到達したときに信号を送るためにプライベートシンクロオブジェクトメンバーが必要になります。絶対に試さないでください:)