私は、独自のプライベート キューとプライベート 'int
*count' メンバーを持つ 4 つのスレッドを持っています。プログラム スレッドからタスクが生成されるときはいつでも、i*t
は最小の 'int count'
*を持つスレッドのキューにエンキューする必要があります。スレッド。*
タスクがキューにプッシュされるたびに、プライベート 'int カウント'
は *タスクがキューからポップされるたびに 1 増加する必要があります*
プライベート 'int カウント' は 1 減少する必要があります
基本的に、プログラム スレッドはプロデューサーであり、4 つのコンシューマー スレッドがあります。各スレッドでキューを使用することにより、メイン スレッドが消費者とやり取りするのにかかる時間を最小限に抑えることができます。NBスレッドが枯渇するか、またはオーバーフローするかどうかを考慮する必要があります。つまり、単一のプロデューサーが 4 つのコンシューマーを保証する速度で「作業」を作成するか、または 4 つのコンシューマーが圧倒されるかです。
素朴なアプローチ
したがって、キュー アクセス/インクリメントを同期する必要があります。つまり、とが変更されmutex
ている間、消費者が何かにアクセスするのを停止する必要があります。同期を行う最も簡単な方法は、メソッド (EG ) をその中にロックすることです。count
queue
enqueue(Item& item)
mutex
C++11 : ミューテックスhttp://en.cppreference.com/w/cpp/thread/mutex
さらに、飢餓が問題 (またはオーバーフロー) である場合は、シグナルを使用して関連するスレッド アクティビティを停止する必要があります (飢餓 - CPU の使用を避けるためにコンシューマーを停止する、オーバーフロー - コンシューマーが追いつく間にプロデューサーを停止する)。通常、これらのシグナルは条件変数を使用して実装されます。
C++11 : 条件変数 : http://en.cppreference.com/w/cpp/thread/condition_variable
そのため、「int カウント」は、タスクの *push,pop 操作
に関して動的に変化し、プログラム スレッドは、カウントが最も低い (または最初のゼロが見つかった) キューにタスクをディスパッチします。
したがって、ここでの状況は少し複雑です。入力するスレッドは、実行する作業が最も少ないスレッドになります。これには、4 を調べてcounts
キューを選択する必要があります。ただし、プロデューサが 1 つしかないため、おそらくロックせずにキューをスキャンできます。ここでのロジックは、コンシューマーが読み取りの影響を受けず、その選択中にコンシューマーが動作していても、スレッドの選択は実際には正しくないということです。
したがって、スレッド オブジェクトの配列があり、それぞれにカウントがあり、ロック用のミューテックスがあります。
1.すべてのプライベート int キュー カウンタを初期化 =0
コンストラクターでカウントを初期化します。初期化中にプロデューサーが動作していないことを確認し、同期が問題にならないようにしてください。
2.counter++ タスクがプッシュされたとき
*3.counter-- タスクがポップされたとき*
スレッド オブジェクトに 2 つのメソッドを実装してエンキュー/デキューを実行し、それぞれで lock_guard を使用してミューテックスをロックします (RAII 手法)。次に、アイテムをキューにプッシュ/ポップし、必要に応じてインクリメント/デクリメントします。
C++11: lock_guard http://en.cppreference.com/w/cpp/thread/lock_guard
4.タスク ディスパッチャは、各スレッドのプライベート int カウントを確認します。
*5.カウント数が最小のキューにタスクをディスパッチ*
getCount()
上で述べたように、オブジェクトが 1 つしかない場合は、オブジェクトの配列をスキャンして、カウンター (メソッドを追加) が最も低いスレッド オブジェクトを選択 (インデックスを維持) するだけです。消費者が仕事を続けていても、それはおそらく最も低いでしょう。
複数のスレッドが作業を生成している場合、同じスレッドにエンキューしている 2 つのスレッドをどのように処理するかを考える必要があるかもしれません (問題ではないかもしれません)。