6

これら 2 つの呼び出しの違いについては、まだよくわかりません。MSDN から、

Monitor.Enter(Object)指定されたオブジェクトの排他ロックを取得します。

Monitor.Wait(Object)オブジェクトのロックを解放し、ロックを再取得するまで現在のスレッドをブロックします。

そのことから、Monitor.Wait は Monitor.Enter と同じであると仮定しますが、再取得する前に最初にオブジェクトのロックを解放する点が異なります。

そもそも現在のスレッドにロックが必要ですか? 別のスレッドがオブジェクトのロックを強制的に解放するにはどうすればよいでしょうか? 同じスレッドがロックを再取得したいのはなぜですか?

4

3 に答える 3

8

MSDNによると: Monitor.Wait Method(Object)

SynchronizationLockException: 呼び出しスレッドは、指定されたオブジェクトのロックを所有していません。

つまり、ロックを取得するために呼び出すのに対し、既にロックを所有Monitor.Wait(Object)している場合にのみ呼び出すことができます。Monitor.Enter(Object)

必要な理由についてMonitor.Wait: 実行を継続するための情報が不足していることにスレッドが気付いた場合 (シグナルを待っているなど)、他のスレッドをクリティカル セクションに入れたいと思うかもしれません。すべてのスレッドが同じ前提条件を持っているわけではないからです。

待機中のスレッドが実行を継続するには、ロックを解放する前にMonitor.Pulse(Object)orを呼び出す必要があります (そうしないと、 と同じ種類の例外が発生します)。Monitor.PulseAll(Object) Monitor.Wait(Object)

パルスの後、ロックが解放された後にロックを取得する次のスレッドは、必ずしもパルスを受信したスレッドではないことに注意してください。

また、パルスを受信することは、条件が満たされることと同じではないことに注意してください。もう少し待つ必要があるかもしれません:

// make sure to synchronize this correctly ;)
while (ConditionNotMet)
{
    Monitor.Wait(mutex);
    if (ConditionNotMet) // We woke up, but our condition is still not met
        Monitor.Pulse(mutex); // Perhaps another waiting thread wants to wake up?
}
于 2013-06-05T14:41:46.903 に答える
1

次の例を検討してください。

public class EnterExitExample
{
    private object myLock;
    private bool running;

    private void ThreadProc1()
    {
        while (running)
        {
            lock (myLock)
            {
                // Do stuff here...
            }
            Thread.Yield();
        }
    }

    private void ThreadProc2()
    {
        while (running)
        {
            lock (myLock)
            {
                // Do other stuff here...
            }
            Thread.Yield();
        }
    }
}

これで 2 つのスレッドができ、それぞれがロックを待機し、処理を実行してからロックを解放します。構文は、 andのlock (myLock)砂糖です。Monitor.Enter(myLock)Monitor.Exit(myLock)

Waitより複雑な例を見てみましょうPulse

public class PulseWaitExample
{
    private Queue<object> queue;
    private bool running;

    private void ProducerThreadProc()
    {
        while (running)
        {
            object produced = ...; // Do production stuff here.
            lock (queue)
            {
                queue.Enqueue(produced);
                Monitor.Pulse(queue);
            }
        }
    }

    private void ConsumerThreadProc()
    {
        while (running)
        {
            object toBeConsumed;
            lock (queue)
            {
                Monitor.Wait(queue);
                toBeConsumed = queue.Dequeue();
            }
            // Do consuming stuff with toBeConsumed here.
        }
    }
}

ここには何がありますか?

生産者は、気が向いたときにいつでもオブジェクトを作成します。取得するとすぐに、彼はキューのロックを取得し、オブジェクトをキューに入れ、Pulse呼び出しを行います。

同時に、消費者はロックを持っていません。彼は を呼び出してロックを解除しましたWait。彼がそのオブジェクトを取得するとすぐにPulse、彼は再ロックし、消費することを行います.

つまり、ここにあるのは、消費者のために何かをする必要があるというスレッド間の直接通知です。それがない場合は、まだ何かすることがあれば、コンシューマーにコレクションのポーリングを継続させることしかできません。を使用Waitすると、存在することを確認できます。

于 2013-06-05T14:46:31.610 に答える