2

O / S Thread.Sleep(10)を実行せずに、協調型/非プリエンプティブなマルチタスクで歩留まりやスリープのデッドロックを回避するための創造的なアイデアはありますか?通常、yieldまたはsleep呼び出しは、他のタスクを実行するためにスケジューラーにコールバックします。しかし、これによりデッドロックが発生する場合があります。

いくつかの背景:

このアプリケーションにはスピードに対する大きなニーズがあり、これまでのところ、同じ業界の他のシステムと比較して非常に高速です。速度の手法の1つは、O / Sスレッドからのコンテキストスイッチのコストではなく、協調的/非プリエンプティブなスレッド化です。

高レベルは、優先度と処理時間に応じてタスクを呼び出す優先度マネージャーを設計します。各タスクは1回の「反復」作業を実行し、優先キューで再び順番を待つために戻ります。

非プリエンプティブスレッドのトリッキーなことは、特定のタスクを作業の途中で停止し、別のタスクからの他のイベントを待ってから続行する場合にどうするかです。

この場合、ABとCの3つのタスクがあります。ここで、AはBとCのアクティビティを同期する必要があるコントローラーです。最初に、AはBとCの両方を開始します。次に、Bが降伏するため、Cが呼び出されます。Cが降伏すると、Aは両方が非アクティブであることを確認し、Bを実行する時間であると判断しますが、Cの時間はまだ決定しません。さて、BはCと呼ばれる歩留まりで立ち往生しているので、実行することはできません。

4

2 に答える 2

1

おそらくこれを処理する最もクリーンな方法は、yielding(しばらくの間十分に処理されたと判断するスレッド)をblocking(特定のイベントを待機する)から分離することだと思います。これにより、降伏したスレッドに時間を与えるのは比較的簡単になりますが、ブロックされたスレッドを実行しようとするデッドロックを回避できます。一般に、どのスレッドが他のどのスレッドをブロックしているかについてトポロジカルソートを実行する必要があるため、他のスレッドが待機しているスレッドに時間を与えることができます。これによりDAGが得られるはずです。グラフ内の任意のサイクルはデッドロックを示します。

于 2010-03-26T07:19:58.290 に答える
0

これに対する理想的な解決策は、C#言語が真の「継続」をサポートしてスタックの幅を広げ、後で中断したところから継続することです。

それがない場合は、この状況のタスクが「isInterrupted」フラグをtrueに設定して戻ることを許可することで、独自の一時的な置き換えを行います。これにより、スタックが巻き戻されます。

次に、スケジューラーがそのタスクの処理時間を再度スケジュールする場合、isInterruptedを確認し、単純なifステートメントを使用して割り込み位置に直接ジャンプするために既に実行された処理をスキップします。

よろしくお願いいたします。ウェイン

于 2010-03-29T22:00:04.497 に答える