C# C“Lock”(“string”)不适用于动态参数?
我使用C#lock来阻止代码执行。如果我们在锁中使用动态字符串输入,它将不起作用C# C“Lock”(“string”)不适用于动态参数?,c#,multithreading,locking,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
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);
}
}
}
在这里,我把Thread.Sleep(20000)-20秒放在Lock语句中。我的预期结果是代码块应该根据参数锁定
有人能帮我继续吗?是的,锁是基于参考值而不是值工作的。当您有两个动态生成的字符串时,它们是不同的实例,这意味着不同的引用,因此它不起作用 如果使用常量字符串,它将正常工作,因为编译时字符串是内部的,但在
锁中使用字符串是个坏主意
- 如果可以公开访问实例,则锁定(这)是一个问题
- 如果MyType是可公开访问的,则锁(typeof(MyType))是一个问题
- 锁(“myLock”)是一个问题,因为进程中使用相同字符串的任何其他代码都将共享相同的锁
引用:在msdn中。是,锁定基于引用值而不是值。当您有两个动态生成的字符串时,它们是不同的实例,这意味着不同的引用,因此它不起作用
如果使用常量字符串,它将正常工作,因为编译时字符串是内部的,但在锁中使用字符串是个坏主意
- 如果可以公开访问实例,则锁定(这)是一个问题
- 如果MyType是可公开访问的,则锁(typeof(MyType))是一个问题
- 锁(“myLock”)是一个问题,因为进程中使用相同字符串的任何其他代码都将共享相同的锁
参考:在msdn。中,您的代码锁定等同于以下内容,因为ToString()
通常在每次调用时创建新字符串:
lock(new object()) { ... }
这显然不会因为每次锁定不同的对象而阻止其他线程执行相同的代码块
您希望锁定与受保护块中访问的数据相关的对象。在您的情况下,它可能是para
本身,也可能是参数
中的其他参考类型值(不能使用值类型B
),如果它在执行过程中没有更改:
lock(para)
{....}
请注意,如果要使用特殊的“锁定”私有对象来保护通过同一类的方法对数据的访问,建议使用这种方法
通过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; } }
}
}
您的代码锁定相当于以下内容,因为ToString()
通常会在每次调用时创建新字符串:
lock(new object()) { ... }
这显然不会因为每次锁定不同的对象而阻止其他线程执行相同的代码块
您希望锁定与受保护块中访问的数据相关的对象。在您的情况下,它可能是para
本身,也可能是参数
中的其他参考类型值(不能使用值类型B
),如果它在执行过程中没有更改:
lock(para)
{....}
请注意,如果要使用特殊的“锁定”私有对象来保护通过同一类的方法对数据的访问,建议使用这种方法
通过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; } }
}
}
如果需要锁定字符串,可以在该字符串上使用。这样做可以锁定字符串引用
lock (string.Intern(parameter.B.ToString()))
{ ... }
但是请注意,与传统的锁对象(private readonly object
)不同,这种类型的锁可以在代码中的任何位置使用,可能会导致同步问题或死锁。如果需要锁定字符串,可以在该字符串上使用。这样做可以锁定字符串引用
lock (string.Intern(parameter.B.ToString()))
{ ... }
但是请注意,与传统的锁对象(private readonly object
)不同,这种类型的锁可以在代码中的任何位置使用,可能会导致同步问题或死锁。oh!。。。有没有其他简单的方法来实现这一点?您应该使用相同的对象来锁定lock(myLocker)
其中我的locker是对象的实例
,由于您的回答,它应该在调用ThreadFun
时共享……但是在我的情况下,两个线程的参数obj可能不相同(在问题中编辑)。两个线程只有参数.B值相同。哦!。。。有没有其他简单的方法来实现这一点?您应该使用相同的对象来锁定lock(myLocker)
其中我的locker是对象的实例
,由于您的回答,它应该在调用ThreadFun
时共享……但是在我的情况下,两个线程的参数obj可能不相同(在问题中编辑)。只有参数.B值对于两个线程都是相同的。多亏了您的回答…但是在我的例子中,参数obj对于两个线程可能都不相同(在问题中编辑)。两个线程只有参数.B值相同。无法锁定值类型。。。您可以尝试将您的值映射到锁定对象,如字典
,并锁定对应于每个值的对象(假设您希望分别保护不同值的片段)…多亏了您的回答…但在我的情况下,两个线程的参数obj可能不相同(有问题的编辑)。两个线程只有参数.B值相同。无法锁定值类型。。。您可以尝试将您的值映射到锁定对象,如字典
,并锁定与每个值对应的对象(假设您希望分别保护不同值的片段)…注意:这个答案在特定场景中有帮助。但这是非常糟糕的做法,应该在生产代码中避免+0:答案很准确,但不能真的投票,因为这确实是个坏主意,可能只会给运营商带来问题。。。请注意,对于ToString()
的默认实现,此代码与锁定单个静态对象lockObject=new object()一样好代码>be