C# 锁(“字符串”)不适用于动态参数?

kom*_*bsh 1 c# multithreading locking

我正在使用 C# 锁来阻止代码执行。如果我们在 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);
            }
        }
    } 
Run Code Online (Sandbox Code Playgroud)

在这里,我将 Thread.Sleep(20000) - 20 秒放入 Lock 语句中。我的预期结果是应该根据参数锁定代码块。B ...

任何人都可以帮助我继续吗?

Ale*_*kov 5

您的代码锁定等效于以下内容,因为ToString()通常在每次调用时都会创建新字符串:

 lock(new object()) { ... }
Run Code Online (Sandbox Code Playgroud)

由于每次锁定不同的对象,这显然不会阻止其他线程执行相同的代码块。

您想锁定以某种方式与在受保护块中访问的数据相关的对象。在你的情况下,如果它在执行过程中没有改变,它可能是它para本身或内部的其他引用类型值parameterB不能使用值类型):

 lock(para)
 {....}
Run Code Online (Sandbox Code Playgroud)

请注意,如果使用特殊的“锁定”私有对象来保护通过同一类的方法对数据的访问,则推荐方法...

通过lock以下方式保护对 2 个属性的访问的类示例:

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; } }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你不能锁定值类型......你可以尝试将你的值映射到像`Dictionary<int, object>`这样的锁定对象并锁定与每个值对应的对象(假设你想分别保护不同值的片段) ... (2认同)

JG *_* SD 5

如果您需要锁定一根绳子,您可以string.Intern在该绳子上使用。这样做可以锁定字符串引用。

lock (string.Intern(parameter.B.ToString()))
{ ... }
Run Code Online (Sandbox Code Playgroud)

但请注意这允许什么,与传统的锁对象 ( private readonly object) 不同,这种类型的锁可以在代码中的任何位置使用,可能会导致同步问题或死锁。

  • 注意:这个答案可以在特定情况下帮助OP。但这是非常糟糕的做法,应该在生产代码中避免! (3认同)
  • @MuthukumarPalaniappan 为什么不呢。您需要全局同步资源的访问,并决定使用`lock("MyLock")`,如果第三方或.net框架库使用相同的`lock("MyLock"){Thread.Sleep(5000)}`怎么办?为什么要与此同步? (2认同)