Locking on field or local variable?

2019-02-21 15:51发布

问题:

After I read this question with an answer from Marc....

I sometimes see people locking on a local variable.

Is this code broken?

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

I believe object o = new Object(); should be outside the method as a Field.

Since each thread is getting a new instance of o , there will be multiple locks.

What am I missing here? Shouldn't it lock on fields in this specific case?

回答1:

I believe object o = new Object(); should be outside the method as a Field.

Since each thread is getting a new instance of o , there will be multiple locks.

Is there anything I'm missing here? cause I know it should lock on fields(in this specific case).

Your understanding is correct. The code is broken.In this implementation even though lock will be active, it will not provide synchronization as it will be on different objects.

From MSDN-lock c#

In general, avoid locking on a public type, or instances beyond your code's control. The common constructs lock (this), lock (typeof (MyType)), and lock ("myLock") violate this guideline:

  • lock (this) is a problem if the instance can be accessed publicly.
  • lock (typeof (MyType)) is a problem if MyType is publicly accessible.
  • lock(“myLock”) is a problem since any other code in the process using the same string, will share the same lock.

Best practice is to define a private object to lock on, or a private static object variable to protect data common to all instances.



回答2:

Yes. It is broken.

You want a static readonly object as a private field to lock on. As you suspect, your example code creates a new object every time you call Do, and hence the lock will have nothing to hold onto and won't work at all.

private static object syncRoot = new object();

lock (syncRoot) { }


回答3:

You are creating the o object every time your method is called. So, lock won't work. I mean other threads won't wait for the lock to be non signaled and grab control over a resource which this lock controls. Usually a lock objects is a private variable in a class so that all methods look into the same object.



回答4:

I, personally, don't see any reason of using this, as lock just sets the special field in the instance of the o, to signaled state. So other threads can check the state of that instance, and based on that execute the code inside the lock statement or wait release of it.

Having local variable every time will allocate a new instance, so for every thread it will be ok.

Don't see any meaning in this.



回答5:

Locking on local variable, the lock won's work. Locking on global variable can take effect to synchronize multiple thread.

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