1

スレッドの操作中にセマフォを使用する方法を理解しようとしています。

同じリソース (Arraylist) を使用する 2 つのスレッドがあります。1 つの方法はリストにランダムな温度を追加し、もう 1 つの方法はリストの平均温度を計算します。

このコンテキストでセマフォ プロパティの Wait および Release を使用するにはどうすればよいですか? また、リストに何かが追加された後に平均温度を計算するスレッドが開始されるように制御するにはどうすればよいですか。

これは私のコードの一部です:

class Temperature
{
    private static Random random = new Random();
    private static ArrayList buffer = new ArrayList();
    static SemaphoreSlim e, b;

    public static void Main (string[] args)
    {
        e = new SemaphoreSlim(6); //how will this work?
        b = new SemaphoreSlim(1);
        Thread t1 = new Thread (Add);
        t1.Start ();
        Thread t2 = new Thread (Average);
        t2.Start ();
    }

    public static void Add()
    {
        int temperature;
        for (int i=0; i<50; i++)
        {
            temperature = random.Next (36, 42);
            Console.WriteLine ("Temperature added to buffer: " + temperature);
            b.Wait ();
            e.Wait ();
            buffer.Add(temperature);
            b.Release ();
            Thread.Sleep (50);
        }
4

5 に答える 5

2

他の人が指摘しているように、ここではセマフォよりも単純なロックの方が適切です。

bufferこれは、同時アクセスから保護しているリソース ( ) が 1 つしかないためです。使用中または使用中でないリソースが 1 つだけの場合は、ロックが最適です。

セマフォは、リソースの容量が限られている場合に役立ちます。例:

バーやナイトクラブのような、火数制限のある会場。人 (スレッド)バウンサー (セマフォ) が会場 (リソース) に容量があることを確認するまで待ちます。最初のクライアントは長く待つ必要はありません。実際、すぐに入れます。

バウンサー (セマフォ) に入ると、カウンターをクリックして、消費された容量を記録します。会場が定員に達すると、キューが構築されます - 人々は中の誰かが去るまで待たなければなりません.

人々が去り (リリース)、用心棒 (セマフォ) がカウンターを減らし、対応する数の人々が入場できるようになります。

したがって、セマフォに容量を設定し、リソースの消費者はそれが利用可能になるのを待ち(容量が利用できない場合はブロックされます)、消費者はリソースの使用が完了したら解放します。

一般的な機能 (必須ではありません) は、リソースの特定の部分が消費されていることを知らない (または気にしない) 場合にセマフォがよく使用されることです。

セマフォとミューテックス

Mutexに似てlockいますが、名前付きのシステム全体のリソースです。aはそれを取得したMutexによって解放される必要がありますが、 aにはスレッド ID がありません。カウントが 1 の が に優先して使用されることがある理由は、これで説明できます。ThreadSemaphoreSemaphoreMutex

于 2013-11-04T19:38:06.220 に答える
2

セマフォは 1 つだけ使用します。

var b = new SemaphoreSlim(1); // 1 -> allow 1 thread to enter the critical section at one time.

次に、それを使用してバッファーを保護します (= クリティカル セクション)。

b.Wait ();
buffer.Add(temperature);
b.Release ();

ロックを使用しても構わない場合は、代わりにこれを使用してください。

private readonly object _locker_ = new object();

次に、lockステートメントでそれを使用します。

lock(_locker_)
{
    buffer.Add(temperature);
}

メソッドで同じことを行うことを忘れないでくださいAverage()

于 2013-11-04T09:15:57.233 に答える
0

初期ゼロSemaphoreを使用して目的のシグナリングを実装できますが、AutoResetEvent代わりに を使用する方がよい場合があります。計算スレッドをイベント ハンドルで待機させ、リストに追加した後にイベントを発生させます。lockただし、@klarkのソリューションのようにsを保持してください。

ジョブに適した同期プリミティブの選択の詳細については、http: //msdn.microsoft.com/en-us/library/ms228964(v=vs.110).aspx を参照してください。

于 2013-11-04T09:56:50.507 に答える