C#使用锁实践
我的应用程序中有一个包含大量代码的关键部分: 在threadMethod中锁定访问的更好方法是: A) 锁定所有块:C#使用锁实践,c#,multithreading,locking,C#,Multithreading,Locking,我的应用程序中有一个包含大量代码的关键部分: 在threadMethod中锁定访问的更好方法是: A) 锁定所有块: private object locker = new object(); private void threadMethod() { while(true) { lock(locker) { // do work - a lot of code here } Thread.Sleep(2000);
private object locker = new object();
private void threadMethod()
{
while(true)
{
lock(locker)
{
// do work - a lot of code here
}
Thread.Sleep(2000);
}
}
B) 使用其他锁定访问成员可以工作:
private static object locker = new object();
private bool canWork;
private bool CanWork
{
get { lock(locker) { return this.canWork; } }
set { lock(locker) { this.canWork = value; } }
}
private void threadMethod()
{
while(true)
{
if(CanWork)
{
// do work - a lot of code here
}
Thread.Sleep(2000);
}
}
在代码的某个地方
CanWork = false;
第二种方法可能会导致比赛条件。你的“大量代码”能被分成几个关键/非关键块吗?两者都不是特别好
- 第一种方法的缺点是你需要长时间持有锁
- 第二种方法的缺点是,检查后状态可能会发生变化
相反,尝试将不可变参数传递给方法(例如数据的副本)。在构造参数和收集结果时,您可能仍然需要锁定,但这希望是一个更短的时间段。我将使用监视器。另外,你真的想要while(true),因为这将永远重复吗
private object syncObject = new object();
private void threadMethod()
{
bool tryToRun = true;
while(tryToRun)
{
if(Monitor.TryEnter(syncObject))
{
tryToRun = false;
// do work - a lot of code here
Monitor.Exit(syncObject);
}
else
{
Thread.Sleep(2000); // Possibly knock this up the how long you expect the lock to be held for.
}
}
}
est链接:
最好的用法是
-声明一个新的私有同步对象
-使用“lock(synObject){code here…}”这两段代码的语义完全不同。请告诉我们更多关于您正在尝试执行的操作,我们将告诉您哪一段代码(如果有)符合您的需要。在属性setters/getter中使用lock语句似乎会导致灾难。同时,请检查您是否真的需要完全查看它,或者是否可以使用类似re的方法aderWriterLockSlim@MattiasK-我不明白为什么这是“灾难配方”-你能解释一下吗?从我的理解Monitor.TryEnter()来看,Monitor不是一个不那么智能的锁吗更好的方法是,当应用程序正在等待获取锁时,它不会暂停。如果另一个线程拥有锁,它只会返回false。然后,您可以在自己的时间稍后重试。在第二种情况下,当“CanWork”成员的状态更改时,工作将在下一个“while”期间完成“循环-哪里有缺点?@UGEEN:在读取值之后,但在实际开始处理该值之前,布尔值可能会变为false(可能是因为另一个线程恰好在同一时间开始处理该值)。在这种情况下,可能会有两个线程执行相同的工作,并且可能会干扰彼此的工作。boolean已锁定-您是指在读取boolean状态后直接发生的情况吗,但在检查“while”条件之前?@UGEEN:我的意思是布尔值在读取后,但在计算if
语句之前可以更改。因此,没有简单的方法-感谢您的时间和回复。是的,但为了保持代码的可读性,我试图避免这种情况-现在我越来越相信,这将很困难