多线程程序中的SQL Server锁异常

时间:2011-04-06 13:07:01

标签: c# sql-server multithreading stored-procedures

在c#程序中,我有2个线程启动存储过程。 此存储过程在一些表中读取和写入数据。

当我启动程序时,我有时会遇到SQL服务器异常(锁定问题)。

为了避免死锁,我尝试在程序中添加lock(this){ ... }以避免同时调用此存储过程但没有成功(相同的例外)

如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

如果类的多个实例正在运行,

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过程中的锁定问题是过程本身的错误,保持事务打开的时间比需要的长,打开不需要的事务,查询次优等等。使sp调用等待在C#代码中,而不是在SQL Server排队等待,并不能解决这些问题。

此外,死锁是一类特殊的问题,几乎总是可以通过重构解决方案来解决数据访问问题。向我们提供有关该问题的更多信息,可能存在根本不需要应用程序级锁定的解决方案。

答案 1 :(得分:0)

正如@SWeko解释的那样,C#的lock只会解决当前AppDomain的线程之间的并发问题,所以如果有多个AppDomain正在运行,那么为了简单起见,让我们说两个桌面客户端,那么它们会遇到僵局。有关详细信息,请参阅Cross-Process Locking in C#What is the difference between lock and Mutex?

即使在桌面应用程序的情况下,处理存储过程中的死锁问题也会好得多。默认行为是您的第二个请求将等到第一个完成的超时,如果您不想等待,则使用WITH(NOWAIT)Explore more