在一个c#程序中,我有两个线程启动一个存储过程。 该存储过程在某些表中读取和写入数据。多线程程序中的Sql服务器锁异常
当我开始我的计划,我有时SQL服务器异常(锁定麻烦)。
为了避免死锁,我想在我的程序,以避免此存储过程的成功(同一除外),但没有同时呼叫
如何修复添加lock(this){ ... }
?
在一个c#程序中,我有两个线程启动一个存储过程。 该存储过程在某些表中读取和写入数据。多线程程序中的Sql服务器锁异常
当我开始我的计划,我有时SQL服务器异常(锁定麻烦)。
为了避免死锁,我想在我的程序,以避免此存储过程的成功(同一除外),但没有同时呼叫
如何修复添加lock(this){ ... }
?
lock(this)
不会解决你的并发问题,如果类的多个实例正在运行,因为锁会参考不同this
引用,即
public class Locker
{
public void Work()
{
lock (this)
{
//do something
}
}
}
用作(假设这些代码中运行并行)
Locker first = new Locker(); Locker second = new Locker();
first.Work() // <-- locks on first second.Work() // <-- locks on second
将锁定在不同的对象上,而不是完全锁定。
使用这种模式
public class Locker
{
private static object lockObject = new object();
// a static doodad for locking
public void Work()
{
lock (lockObject)
{
//do something
}
}
}
将锁定在两种情况下,同样的事情,并进行第二个呼叫等待。
但是,从我的经验,多数情况下,在SQL Server程序锁定问题是程序本身的故障,持有交易比neccessary开放的时间越长,开不必要的交易,有次优查询等让您的SP调用在C#代码中排队等待,而不是在SQL Server中排队,并不能解决这些问题。
另外,死锁是并发性问题的一个特定的类别,几乎总是可以通过重构时考虑到数据访问的解决方案来解决。给我们提供关于这个问题的更多信息,可能有一个解决方案根本不需要应用程序级锁。
正如@SWeko所解释的那样,C#的lock
只能解决当前AppDomain的线程之间的并发问题,所以如果有多个AppDomain在运行,为了简单起见我们说两个桌面客户端,然后它们将会陷入死锁。有关更多详细信息,请参阅Cross-Process Locking in C#和What is the difference between lock and Mutex?。
它会好得多,即使在桌面应用程序的情况下,你处理死锁问题您的存储过程中。默认行为是您的第二个请求会等到第一个完成的超时,如果您不想等待,请使用WITH(NOWAIT)
。 Explore more
如果你能证明在SP代码这将是一个更容易弄清楚为什么你得到一个僵局。 – 2011-04-06 13:13:05