4

複数のスレッドを持つアプリケーションでロック オブジェクトを使用しています。

他のスレッドがロックされたオブジェクトに対して何回作業を試みたか、またはロックされたオブジェクトを更新しようとして無駄にした時間を確認するにはどうすればよいですか?

私のコードは、ここのベストアンサーに基づいています:

配列を更新する複数のスレッド

編集:コピーされたコード:

float[] bestResult;
object sync = new Object();

lock (sync) 
{
    if (bestResult[0] > calculatedData[0]) {
        bestResult = calculatedData;
    }
}
4

4 に答える 4

6

System.Diagnostics.Stopwatchクラスはここであなたを助けるかもしれません:

float[] bestResult;
object sync = new Object();
var sw = new System.Diagnostics.Stopwatch();
sw.Start();

lock (sync) 
{
    sw.Stop();
    if (bestResult[0] > calculatedData[0]) {
        bestResult = calculatedData;
    }
}

Console.WriteLine("Time spent waiting: " + sw.Elapsed);
于 2012-10-23T22:04:09.490 に答える
1

問われているのは、ロック要求が発生した回数、またはロックの競合によって無駄になった時間をどのように判断するかということです。

尋ねられた質問に対する答えは、Visual Studio Premium Edition で提供されるようなプロファイラーを使用することです。他の .NET プロファイラーが存在する場合があります。

独自のロックの問題があるため、すべてのロック ステートメントにカウント/タイミング コードを追加することは実際的ではありません。したがって、プロファイラーがない場合は、静的分析を実行する必要があります。これはそれほど悲惨ではありません。ネストされたループは大きな手がかりです。

ロックの競合は、サーバーの設計において最大の脅威となります。幸いなことに、ユーザーのセッション状態はセッションに対して非公開です。APM (非同期プログラミング モデル - 本質的にコールバック) を使用している場合、ハンドラーの最後まで socket.BeginRead を呼び出さない限り、セッションの観点から、状態に対する操作は事実上シングル スレッドです。したがって、これらの条件下では、ロックはセッションのセットアップと破棄にのみ必要です。セッション内では完全に不要です。

これが、同時実行を処理するための新しくファッショナブルな方法よりも APM を好む理由です。

于 2012-10-24T01:51:25.190 に答える
0

私はスレッドの専門家ではありませんが、他のスレッドがオブジェクトを処理しようとした回数を取得するには、おそらくより原始的なバージョンのロックメカニズムを実装する必要がありLockます。しっかりとループしたモニターを使って、以下のショットを撮りました。TryEnterとコメントを歓迎します。

もちろん、このようなものを単独で実装すると、必要なカウントを取得するために、またこの実装が内部でのロックの動作とはまったく同じではないという事実に基づいて、ブロック時間が長くなり、ブロックが増える可能性があります。とにかく時間を費やしたので投稿します。

   class Program
    {
        static object lockObj = new object();
        static void Main(string[] args)
        {
            System.Threading.Thread t = new System.Threading.Thread(proc);
            System.Threading.Thread t2 = new System.Threading.Thread(proc);
            t.Start();
            t2.Start();
            t.Join();
            t2.Join();
            Console.WriteLine("Total locked up time = " + (LockWithCount.TotalWaitTicks / 10000) + "ms");
            Console.WriteLine("Total blocks = " + LockWithCount.TotalBlocks);
            Console.ReadLine();
        }

        static void proc()
        {
            for (int x = 0; x < 100; x++)
            {
                using (new LockWithCount(lockObj))
                {
                    System.Threading.Thread.Sleep(10);
                }
            }
        }
    }

Lock() {}上記は、既存のものをで置き換えることによってLockWithCountを使用する方法を示していますusing(new LockWithCount(x)) {}

 class LockWithCount : IDisposable
{
    static System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
    object lockObj;
    public static long TotalWaitTicks = 0;
    public static long TotalBlocks = 0;
    static LockWithCount()
    {
        watch.Start();
    }

    public LockWithCount(object obj)
    {
        lockObj = obj;
        long startTicks = watch.ElapsedTicks;
        if (!System.Threading.Monitor.TryEnter(lockObj))
        {
            System.Threading.Interlocked.Increment(ref TotalBlocks);
            System.Threading.Monitor.Enter(lockObj);
            System.Threading.Interlocked.Add(ref TotalWaitTicks, watch.ElapsedTicks - startTicks);
        }
    }


    public void Dispose()
    {
        System.Threading.Monitor.Exit(lockObj);
    }
}
于 2012-10-23T22:56:01.063 に答える