9

マークからの回答でこの質問を読んだ後....

ローカル変数をロックしている人を時々見かけます。

このコードは壊れていますか?

public void Do()
{
 object  o  = new Object();
 lock (o)
     {
      ...
     }
}

としてメソッドのobject o = new Object();にある必要があると思います。Field

各スレッドは の新しいインスタンスを取得しているため、o複数のロックが発生します。

ここで何が欠けていますか?この特定のケースでは、フィールドをロックするべきではありませんか?

4

5 に答える 5

8

object o = new Object();としてメソッドの外にある必要があると思いますField

各スレッドは の新しいインスタンスを取得しているため、o複数のロックが発生します。

ここで何が欠けていますか?この特定のケースでは、フィールドをロックするべきではありませんか?

あなたの理解は正しいです。コードが壊れています。この実装では、ロックがアクティブになりますが、別のオブジェクトにあるため、同期は提供されません。

Microsoft Docsから

共有リソースへのスレッド アクセスを同期するときは、専用のオブジェクト インスタンス (たとえば、プライベートな読み取り専用オブジェクト balanceLock = new object();) またはコードの無関係な部分によってロック オブジェクトとして使用される可能性が低い別のインスタンスをロックします。 . デッドロックやロックの競合が発生する可能性があるため、異なる共有リソースに同じロック オブジェクト インスタンスを使用することは避けてください。特に、以下をロック オブジェクトとして使用しないでください。

これは、呼び出し元がロックとして使用する可能性があるためです。typeof 演算子またはリフレクションによって取得される可能性がある型インスタンス。文字列リテラルを含む文字列インスタンス (インターンされる可能性があるため)。ロックの競合を減らすために、ロックを保持する時間をできるだけ短くします。

于 2013-01-07T09:48:09.143 に答える
4

はい。これは壊れています。

ロックするプライベート フィールドとして静的な読み取り専用オブジェクトが必要です。ご想像のとおり、コード例では Do を呼び出すたびに新しいオブジェクトが作成されるため、ロックは保持するものがなく、まったく機能しません。

private static object syncRoot = new object();

lock (syncRoot) { }
于 2013-01-07T09:45:02.080 に答える
2

メソッドが呼び出されるたびに o オブジェクトを作成しています。なので、ロックは効きません。つまり、他のスレッドは、ロックが非シグナル状態になるのを待たず、このロックが制御するリソースを制御します。通常、ロック オブジェクトはクラス内のプライベート変数であるため、すべてのメソッドが同じオブジェクトを参照します。

于 2013-01-07T09:40:50.270 に答える
2

個人的には、のインスタンスlock特別なフィールドをシグナル状態に設定するだけなので、これを使用する理由はわかりません。したがって、他のスレッドはそのインスタンスの状態をチェックし、それに基づいてステートメント内のコードを実行するか、その解放を待つことができます。olock

毎回ローカル変数を持つと新しいインスタンスが割り当てられるため、すべてのスレッドで問題ありません。

これには何の意味もありません。

于 2013-01-07T09:40:54.757 に答える
1

ローカル変数をロックすると、ロックが機能しなくなります。グローバル変数のロックは、複数のスレッドを同期するために有効になります。

using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
        using System.Threading.Tasks;
        using System.Threading;

        namespace testLock
        {
            class Program
            {
                public static void Main()
                {
                    // Start a thread that calls a parameterized static method.
                    for(int i = 0; i< 10;i++)
                    {
                        Thread newThread = new Thread(DoWork);
                        newThread.Start(i);
                    }

                    Console.ReadLine();
                }

                static object gObject= new object();
                public static void DoWork(object data)
                {
                    int len = (int)data % 3;
                    object tmp = new object();
                    Console.WriteLine("to lock...... Data='{0}'  sleepTime:{1}", data, len);
                    lock (tmp)//tmp won't work, change tmp to gObject to see different output, which is good locking case)
                    {
                        Console.WriteLine("in lock...... Data='{0}'  sleepTime:{1}", data, len);

                        Thread.Sleep(  len* 1000);
                        Console.WriteLine("Static thread procedure. Data='{0}'  sleepTime:{1}", data, len);
                    }
                }

            }
        }

    **Lock temp variable,will output:**
    to lock...... Data='1'  sleepTime:1
    in lock...... Data='1'  sleepTime:1
    to lock...... Data='2'  sleepTime:2
    in lock...... Data='2'  sleepTime:2
    to lock...... Data='0'  sleepTime:0
    in lock...... Data='0'  sleepTime:0
    Static thread procedure. Data='0'  sleepTime:0
    to lock...... Data='3'  sleepTime:0
    in lock...... Data='3'  sleepTime:0
    Static thread procedure. Data='3'  sleepTime:0
    to lock...... Data='4'  sleepTime:1
    in lock...... Data='4'  sleepTime:1
    to lock...... Data='5'  sleepTime:2
    in lock...... Data='5'  sleepTime:2
    to lock...... Data='6'  sleepTime:0
    in lock...... Data='6'  sleepTime:0
    Static thread procedure. Data='6'  sleepTime:0
    to lock...... Data='7'  sleepTime:1
    in lock...... Data='7'  sleepTime:1
    to lock...... Data='8'  sleepTime:2
    in lock...... Data='8'  sleepTime:2
    to lock...... Data='9'  sleepTime:0
    in lock...... Data='9'  sleepTime:0
    Static thread procedure. Data='9'  sleepTime:0
    Static thread procedure. Data='1'  sleepTime:1
    Static thread procedure. Data='4'  sleepTime:1
    Static thread procedure. Data='7'  sleepTime:1
    Static thread procedure. Data='2'  sleepTime:2
    Static thread procedure. Data='5'  sleepTime:2
    Static thread procedure. Data='8'  sleepTime:2

    **Then lock gObject, will print:**
    to lock...... Data='0'  sleepTime:0
    in lock...... Data='0'  sleepTime:0
    to lock...... Data='1'  sleepTime:1
    to lock...... Data='2'  sleepTime:2
    Static thread procedure. Data='0'  sleepTime:0
    in lock...... Data='1'  sleepTime:1
    to lock...... Data='3'  sleepTime:0
    to lock...... Data='4'  sleepTime:1
    to lock...... Data='5'  sleepTime:2
    to lock...... Data='6'  sleepTime:0
    to lock...... Data='7'  sleepTime:1
    to lock...... Data='8'  sleepTime:2
    to lock...... Data='9'  sleepTime:0
    Static thread procedure. Data='1'  sleepTime:1
    in lock...... Data='5'  sleepTime:2
    Static thread procedure. Data='5'  sleepTime:2
    in lock...... Data='9'  sleepTime:0
    Static thread procedure. Data='9'  sleepTime:0
    in lock...... Data='2'  sleepTime:2
    Static thread procedure. Data='2'  sleepTime:2
    in lock...... Data='8'  sleepTime:2
    Static thread procedure. Data='8'  sleepTime:2
    in lock...... Data='7'  sleepTime:1
    Static thread procedure. Data='7'  sleepTime:1
    in lock...... Data='4'  sleepTime:1
    Static thread procedure. Data='4'  sleepTime:1
    in lock...... Data='3'  sleepTime:0
    Static thread procedure. Data='3'  sleepTime:0
    in lock...... Data='6'  sleepTime:0
    Static thread procedure. Data='6'  sleepTime:0
于 2017-08-26T09:00:30.733 に答える