1

私はそのようなコードを持っています:

public void TablesUpdated(object sender, TablesUpdatedArgs args)
{
    lock (quotesLock)
    {
        while (!args.quotesQueue.IsNullOrEmpty())
            quotes.Enqueue(args.quotesQueue.Dequeue());
    }
    lock (securitiesLock)
    {
        while (!args.securitiesUpdates.IsNullOrEmpty())
            securities.Enqueue(args.securitiesUpdates.Dequeue());
    }
    lock (orderUpdatesLock)
    {
        while (!args.orderUpdates.IsNullOrEmpty())
            orderUpdates.Enqueue(args.orderUpdates.Dequeue());
    }
}

このコードの問題は、コードlockの他の部分を処理できる可能性がある間、私が待っていることです。そして、私が待っている間、コードの他の部分がロックされる可能性があります!

quotesLock0〜1秒のsecuritiesLock間ビジーであり、1〜2秒のorderUpdatesLock間ビジーであり、2〜3秒の間ビジーであると仮定します。私のコードは、注文のために3秒間完全にブロックされます。

しかしqoutesLock、最後になる場合:

public void TablesUpdated(object sender, TablesUpdatedArgs args)
{
    lock (securitiesLock)
    {
        while (!args.securitiesUpdates.IsNullOrEmpty())
            securities.Enqueue(args.securitiesUpdates.Dequeue());
    }
    lock (orderUpdatesLock)
    {
        while (!args.orderUpdates.IsNullOrEmpty())
            orderUpdates.Enqueue(args.orderUpdates.Dequeue());
    }
    lock (quotesLock)
    {
        while (!args.quotesQueue.IsNullOrEmpty())
            quotes.Enqueue(args.quotesQueue.Dequeue());
    }
}

コードは1秒で実行されます。

問題は、コードを次のように書き直す方法です。

  • 一部のロックを取得できない場合は、他のロックが処理中です
  • 余分なスレッドは作成されません(コストがかかりすぎるため)。

おそらく、多くのメソッドを使用して非常に複雑なwhileループを作成する必要があります。TryEnterまたは何が良いでしょうか?

現実のロックのupdは、非常に短い時間(約5〜15マイクロ秒)保持されます。したがって、別のスレッドに移動するのは得策ではない可能性があります。すべてを同じスレッドで実行する必要があると思います。

4

1 に答える 1

2

これらのタスクは相互にまったく依存していないため、それらを並列化するのが最善です。

これを行う1つの方法は次のとおりです。

Parallel.Invoke(new ParallelOptions(), () =>
    {
        lock (securitiesLock)
        {
            while (!args.securitiesUpdates.IsNullOrEmpty())
                securities.Enqueue(args.securitiesUpdates.Dequeue());
        }
    },
    () =>
    {
        lock (orderUpdatesLock)
        {
            while (!args.orderUpdates.IsNullOrEmpty())
                orderUpdates.Enqueue(args.orderUpdates.Dequeue());
        }
    },
    () =>
    {
        lock (quotesLock)
        {
            while (!args.quotesQueue.IsNullOrEmpty())
                quotes.Enqueue(args.quotesQueue.Dequeue());
        }
    });

あなたはかなり長い間ロックが保持されていることについて話しているので、これは正味の勝利である可能性が非常に高いです。スレッドプールスレッドに依存するため(したがって、3つのハードスレッドを作成する必要はほとんどありませんが、すでに存在する場合はそれらを使用できます)、スレッドのオーバーヘッドの多くを排除できます。他に何もないとしても、それは現在のオプションとあなたが作成する他のソリューションに対してベンチマークを行うための1つのオプションです。

于 2013-01-03T16:52:43.633 に答える