C# 锁定操作不起作用
我遇到了一些锁定C# 锁定操作不起作用,c#,multithreading,locking,C#,Multithreading,Locking,我遇到了一些锁定操作的代码,发现它不起作用。下面是代码的(简化和愚蠢)版本: class Program { static void Main(string[] args) { var settings = new Settings(0); Action<int> threadAction = i => { BusyBody.DoSomething(settings.GetANumber,
操作的代码,发现它不起作用。下面是代码的(简化和愚蠢)版本:
class Program
{
static void Main(string[] args)
{
var settings = new Settings(0);
Action<int> threadAction = i =>
{
BusyBody.DoSomething(settings.GetANumber, settings.SetANumber, i);
};
ThreadPool.QueueUserWorkItem(delegate { threadAction(1); });
ThreadPool.QueueUserWorkItem(delegate { threadAction(2); });
Console.ReadLine();
}
class Settings
{
int i;
public Settings(int i)
{
this.i = i;
}
public int GetANumber() => i;
public void SetANumber(int i) => this.i = i;
}
class BusyBody
{
public static void DoSomething(Func<int> getInt, Action<int> setInt, int i)
{
lock (setInt)
{
Console.WriteLine("Getting int: " + getInt());
Console.WriteLine("i " + i);
setInt(i);
Console.WriteLine("set");
}
}
}
}
或
取决于哪个线程首先通过锁。然而,这不是我所看到的。相反,我看到:
Getting int: 0
i 2
Getting int: 0
i 1
set
set
看起来两个线程都进入了锁
。为什么会发生这种情况?被锁定的操作
是来自同一对象的同一方法,因此引用不应该相同吗
任何帮助都将不胜感激。谢谢 当您多次将方法强制转换为操作
时(当您传递设置.SetANumber
时),这并不意味着您得到相同的操作
对象。您可以得到多个执行相同操作的操作对象
试试这个:
Action<int> set_action = settings.SetANumber;
Action<int> threadAction = i =>
{
BusyBody.DoSomething(settings.GetANumber, set_action, i);
};
Action set\u Action=settings.SetANumber;
动作线程动作=i=>
{
爱管闲事的人。做某事(settings.GetANumber,set_action,i);
};
这确保您有一个操作对象。这里的问题是您锁定了两个不同的对象
这一行:
BusyBody.DoSomething(settings.GetANumber, settings.SetANumber, i);
是这个的缩写:
BusyBody.DoSomething(new Func<int>(settings.GetANumber), new Action<int>(settings.SetANumber), i);
BusyBody.DoSomething(新函数(settings.GetANumber)、新操作(settings.SetANumber)、i);
两个newfunc(…)
和newaction(…)
表达式将在每次调用时生成新的委托对象,因此您不会锁定同一个对象实例
如果要共享这些对象,必须创建一次:
...
Func<int> getANumber = settings.GetANumber;
Action<int> setANumber = settings.SetANumber;
Action<int> threadAction = i =>
{
BusyBody.DoSomething(getANumber, setANumber, i);
};
...
。。。
Func getANumber=settings.getANumber;
Action setANumber=settings.setANumber;
动作线程动作=i=>
{
爱管闲事的人。做某事(getANumber,setANumber,i);
};
...
我认为发生的事情是,您正在创建并锁定引用相同方法的两个不同的委托
对象。但我不知道如何更正式地表达它。飞碟?“然而这不是我看到的”。你能告诉我们你看到了什么吗?@YacoubMassad用我看到的输出更新了问题。
BusyBody.DoSomething(new Func<int>(settings.GetANumber), new Action<int>(settings.SetANumber), i);
...
Func<int> getANumber = settings.GetANumber;
Action<int> setANumber = settings.SetANumber;
Action<int> threadAction = i =>
{
BusyBody.DoSomething(getANumber, setANumber, i);
};
...