Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Lock ("string") not working for dynamic argument?

I am using C# lock to block code execution. It is not working if we use dynamic string input in Lock.

public class ParameterClass
    {
        public string A = string.Empty;
        public Int64 B = 0;
    }

    class Program
    {
        static void Main(string[] args)
        {
            ParameterClass parm = new ParameterClass { A = "Test", B = 1 };
            Thread thread = new Thread(ThreadFun);
            thread.Start(parm);

            System.Threading.Thread.Sleep(2000);

            parm = new ParameterClass { A = "Test", B = 1 };
            ThreadFun(parm);
        }

        public static void ThreadFun(object para)
        {
            ParameterClass parameter = (ParameterClass)para;
            lock (parameter.B.ToString())
            {
                Console.WriteLine(DateTime.Now);
                System.Threading.Thread.Sleep(20000);
            }
        }
    } 

Here , I have put Thread.Sleep(20000) - 20 seconds inside Lock statement. my expected result is the code block should be locked based on parameter.B...

Can anyone help me to proceed?

like image 555
kombsh Avatar asked Jun 16 '26 14:06

kombsh


2 Answers

If you need to lock upon a string you can use string.Intern on the string. Doing this you lock on the string reference.

lock (string.Intern(parameter.B.ToString()))
{ ... }

But be aware what this allows, unlike traditional lock objects (private readonly object) this type of lock can used anywhere in the code, potentially causing synchronization issues or deadlocks.

like image 187
JG in SD Avatar answered Jun 19 '26 03:06

JG in SD


Your code locking is equivalent to following since ToString() normally create new string on every call:

 lock(new object()) { ... }

which clearly not going to prevent other threads to execute the same block of code due to locking on different object each time.

You want to lock on object that somehow relates to data accessed in the protected block. In your case it may be either para itself or other reference type value inside parameter (value type B can't be used) if it does not change during execution:

 lock(para)
 {....}

Note that recommended approach if to have special "locking" private object that used to protect access to the data via methods of the same class...

Sample of the class that protects access to 2 properties via lock:

public class ParameterClass
{   
    private object lockObject = new object();
    private string a = string.Empty;
    private Int64 b = 0;

    public SafeSet(string v, long number)
    {
        lock(lockObject) 
        {
             a = v;
             b = number;
        }
    }

    public string A
    {
        get { lock(lockObject)  { return a; } }
    }

    public long B
    {
        get { lock(lockObject)  { return b; } }
    }
}
like image 31
Alexei Levenkov Avatar answered Jun 19 '26 04:06

Alexei Levenkov