2

私はCに非常に慣れていないので、この質問が非常にずれている場合は申し訳ありません. Java executor サービスを使用して固定スレッド プールを作成しましたが、C で同様のことを行う方法を理解するのに苦労していました。

pthreads を使用して c でスレッドを作成する方法を学びましたが (これは十分に簡単に思えます)、一定数のスレッドが消費するキューを作成する方法がわかりません。これまでに行ったすべてのチュートリアルでは、スレッドをメイン ステートメントで独自に開始するか、for ループ内で開始します。このアプローチを行うと、数百万のスレッド (作業項目ごとに 1 つ) が必要になりますが、3 つまたは 4 つしか必要なく、それらにキューを処理させます。

これは可能ですか? もしそうなら、何を学ぶ必要がありますか? pthreads でそれが不可能な場合は、別のものを喜んで使用します。Mac で開発していて、Linux にデプロイするつもりです。

4

1 に答える 1

2

これは、条件変数を使用することで、ユニプロデューサー/マルチコンシューマー モデルでかなり簡単に行うことができます。これは1 つのアーキテクチャであり、他のアーキテクチャも可能であることを覚えておいてください。

メイン スレッドでは、キュー、ミューテックス、および条件変数を作成し、実行したい数のスレッドを起動するだけです。次のような擬似コードです。

glbQueue = []
glbMutex = new mutex
glbCondVar = new condvar
for i = 1 to 10:
    start thread using thrdFn

次のステップは、必要なワークアイテムを (ミューテックスを使用して) キューに追加し、条件変数をキックして、必要に応じてスレッドをウェイクアップすることです。

while workitem = getNextWorkItem():
    lock glbMutex
    glbQueue.append (workItem)
    kick glbCondVar
    unlock glbMutex

すべての作業項目が完了したら、キューが空になるのを待ってから、いくつかの番兵項目を投稿してスレッドをシャットダウンし、それらが終了するのを待ってから終了します。

lock glbMutex
while glbQueue is not empty:
    kick glbCondVar
    unlock glbMutex.
    sleep for a bit
    lock glbMutex
unlock glbMutex.

for i = 1 to 10:
    lock glbMutex
    glbQueue.append (endWorkItem)
    kick glbCondVar
    unlock glbMutex.
    wait for any one thread to exit
exit

作業を行うスレッドも比較的単純です。まず、条件変数がキックされるのを待って無限ループで実行されます。そのループ内で、使用可能なワークアイテムがなくなるまで処理し、その後スリープ状態に戻ります。

スレッドが最終作業項目を受け取ると終了し、各スレッドが 1 つの最終項目を取得することが保証されます。

つまり、次のようなものです。

initialise
stillGoing = true
lock glbMutex
while stillGoing:
    wait on glbCondVar using glbMutex
    while stillGoing and glbQueue is not empty:
        extract workItem from glbQueue to thread local storage
        unlock glbMutex.
        if workItem is endWorkItem:
            stillGoing = false
        else:
            do the work specified by workItem
        lock glbMutex
unlock glbMutex
clean up
exit thread

これにより、基本的に、キューでアイテムを処理するスレッドの数を固定でき、キュー自体はミューテックスによって保護されるため、ワーカー スレッドとメイン スレッドの間で競合が発生することはありません。

于 2012-09-03T08:50:28.350 に答える