2

現在、マルチスレッドと C# での使用法を学んでいます。だから、私は以下のような問題に直面しています:(私のとても単純な質問で申し訳ありません)

Producer と Consumer という名前の 2 つのクラスがあるとします。プロデューサ タスクはプログラムの実行中に 4 つの数値を生成し、コンシューマ タスクはそれらの数値を消費して使用し、プログラムの最後にそれらの合計を返します。

消費者クラスの定義:

class Consumer
{
    private HoldInteger sharedLocation;
    private Random randomSleepTime;

    public Consumer(HoldInteger shared, Random random)
    {
        sharedLocation = shared;
        randomSleepTime = random;
    }

    public void Consume()
    {
        int sum = 0;

        for (int i = 1; i <= 4; i++)
        {
            Thread.Sleep(randomSleepTime.Next(1, 3000));
            sum += sharedLocation.Buffer;
        }
    }
}

また、Producer クラスの定義は次のとおりです。

class Producer
{
    private HoldInteger sharedLocation;
    private Random randomSleepTime;

    public Producer(HoldInteger shared, Random random)
    {
        sharedLocation = shared;
        randomSleepTime = random;
    }

    public void Produce()
    {
        for (int i = 1; i <= 4; i++)
        {
            Thread.Sleep(randomSleepTime.Next(1, 3000));
            sharedLocation.Buffer = i;
        }
    }
}

また、HoldIntegerプロデューサーがこの変数を書き込み、コンシューマーがそこから読み取る Buffer 変数を含むクラスがあります。これらのクラスを組み合わせて、メイン メソッドで以下のコードをプログラムします。

static void Main(string[] args)
{
   HoldInteger holdInteger = new HoldInteger();
   Random random = new Random();

   Producer producer = new Producer(holdInteger, random);

   Consumer consumer = new Consumer(holdInteger, random);

   Thread producerThread = new Thread(new ThreadStart(producer.Produce));
   producerThread.Name = "producer";

   Thread consumerThread = new Thread(new ThreadStart(consumer.Consume));
   consumerThread.Name = "consumer";

   producerThread.Start();
   consumerThread.Start();
}

それで、私の質問はそれですHow can i manage this relationship With Low Memory and Time Wasting ?

HoldIntegerこれらのスレッド管理コードはクラス本体に配置されることに注意してください。

ご清聴ありがとうございました。

4

2 に答える 2

4

HoldIntegerクラスをBlockingQueueに置き換えます。ここで実装を見つけることができます。実装の背後にある理由の詳細については、この質問を確認してください。.NET4.0にもブロッキングキューがあるのではないかと思います。このアプローチにより、その後、管理がはるかに簡単になります。

class Producer
{
    //...

    public void Produce()
    {
        for (int i = 1; i <= 4; i++)
        {
            Thread.Sleep(randomSleepTime.Next(1, 3000));
            blockingIntQueue.Enqueue(i);
        }
    }
}

消費者は次のようになります。

class Consumer
{
    //...

    public void Consume()
    {
        int value = 0;
        for (int i = 1; i <= 4; i++)
        {
            if( blockingIntQueue.TryDequeue(out value) )
            {
                sum += value;
            }
        }
    }
}

HoldIntegerただし、 (これが何らかの要件である場合)保持したい場合はHoldIntegerUnsynchronized、バッファーを使用する代わりにクラス内にブロッキングキューを配置でき(簡単なことです)、同じ結果が得られます。

注:このアプローチでは、スレッドが正確に適切なタイミングでウェイクアップしないため、値の欠落や古い値の読み取りについて心配する必要がなくなります。「バッファ」の使用に関する潜在的な問題は次のとおりです。

整数ホルダーが基になる「バッファー」を安全に処理する場合でも、必要なすべての整数を取得できる保証はありません。これを考慮に入れてください:

ケース1

Producer wakes up and writes integer.
Consumer wakes up and reads integer.

Consumer wakes up and reads integer.
Producer wakes up and writes integer.

ケース2

Consumer wakes reads integer.
Producer wakes up and writes integer.

Producer wakes up and writes integer.
Consumer wakes up and reads integer.

タイマーは十分に正確ではないため、この種のことは完全に可能であり、前者の場合は消費者に古い値を読み取らせ、後者の場合は消費者に値を見逃させます。

于 2011-08-23T21:25:11.793 に答える
1

次のようなことができます

class HoldIntegerUnsynchronized {
    int buffer;
    object syncLock = new object();
    bool goodToRead = false;
    bool goodToWrite = true;

    public int Buffer {
       get {
           lock (syncLock) {
               while (!goodToWrite)
                   Monitor.Wait(syncLock);
               buffer = value;
               goodToWrite = false;
               goodToRead = true;
               Monitor.Pulse(syncLock);
           }
       }
       set {
           lock (syncLock) {
               while (!goodToRead)
                   Monitor.Wait(syncLock);
               int toReturn = buffer;
               goodToWrite = true;
               goodToRead = false;
               Monitor.Pulse(syncLock);
               return toReturn;
           }
       }
    }
}

このコードはテストしていないことに注意してください。

于 2011-08-23T21:26:48.867 に答える