9

複数のスレッドがすべて同じロックで待機している場合、ロックを取得する際にメイン スレッドの優先度を高くすることができます。つまり、ワーカー スレッドがlockメイン スレッドの前にステートメントに移動すると、メイン スレッドは、既にロックを待機している他のスレッドよりも先にロックを取得します。

4

3 に答える 3

8

いいえ、lockステートメントはSystem.Threading.Monitor.Enter()( MSDN ) にマップされ、優先度パラメーターを受け入れるオーバーロードはありません。

私が考えることができる最も近いものは ReaderWriterLock(Slim) ですが、この要求につながる設計を真剣に再考します。必要なものを達成するためのより良い方法がおそらくあります。

于 2012-10-17T20:43:54.513 に答える
2

ネイティブ ロック ステートメントでは、いいえ。開発に時間と労力を費やす意思がある場合は、独自のカスタム ロック メカニズムを使用してください。

これが私のドラフトAAソリューションです。機能する場合と機能しない場合があり、非常に効率的ではない場合もありますが、少なくとも出発点です。

public class Lock
{
    bool locked = false;

    private object key = new object();
    SortedDictionary<int, Queue<ManualResetEvent>> notifiers =
        new SortedDictionary<int, Queue<ManualResetEvent>>();

    ManualResetEvent specialNotifier = null;

    public void Lock()
    {
        lock (key)
        {
            if (locked)
            {
                ManualResetEvent notifier = new ManualResetEvent(false);

                int priority = getPriorityForThread();

                Queue<ManualResetEvent> queue = notifiers[priority];
                if (queue == null)
                {
                    queue = new Queue<ManualResetEvent>();
                    notifiers[priority] = queue;
                }

                queue.Enqueue(notifier);

                notifier.WaitOne();
            }
            else
            {
                locked = true;
            }
        }
    }

    private static int getPriorityForThread()
    {
        return 0;
    }

    public void Release()
    {
        lock (key)
        {
            foreach (var queue in notifiers.Values)
            {
                if (queue.Any())
                {
                    var notifier = queue.Dequeue();
                    notifier.Set();
                    return;
                }
            }
            locked = false;
        }
    }
}
于 2012-10-17T21:17:01.353 に答える
1

ここに別の解決策があります。たくさんの線がありますが、とてもシンプルです。関数DoSomethingSingleは一度に 1 つのスレッドだけが呼び出され、highPriorityフラグを持つスレッドが優先されます。

    static int numWaiting = 0;
    static object single = new object();

    ResultType DoSomething(string[] argList, bool highPriority = false)
    {
        try
        {
            if (highPriority)
            {
                Interlocked.Increment(ref numWaiting);
            }

            for (;;)
            {
                lock (single)
                {
                    if (highPriority || numWaiting == 0)
                    {
                        return DoSomethingSingle(argList);
                    }
                }
                // Sleep gives other threads a chance to enter the lock
                Thread.Sleep(0);
            }
        }
        finally
        {
            if (highPriority)
            {
                Interlocked.Decrement(ref numWaiting);
            }
        }
    }

これにより、2 つの優先レベルが可能になります。優先度の低いスレッドは、それを待っている優先度の高いスレッドがない場合にのみリソースへのアクセスを取得することが保証されています。

編集: incr/dec をインターロックするように変更

于 2016-07-01T15:51:04.623 に答える