我看到,对于使用非线程安全的对象,我们用这样的锁包装代码:
private static readonly Object obj = new Object();
lock (obj)
{
// thread unsafe code
}
那么,当多个线程访问相同的代码时会发生什么(让我们假设它运行在一个ASP。NET web应用程序)。他们排队了吗?如果是的话,他们要等多久?
使用锁对性能有什么影响?
我看到,对于使用非线程安全的对象,我们用这样的锁包装代码:
private static readonly Object obj = new Object();
lock (obj)
{
// thread unsafe code
}
那么,当多个线程访问相同的代码时会发生什么(让我们假设它运行在一个ASP。NET web应用程序)。他们排队了吗?如果是的话,他们要等多久?
使用锁对性能有什么影响?
当前回答
锁语句中的部分只能由一个线程执行,因此所有其他线程将无限期地等待持有锁的线程完成。这可能导致所谓的死锁。
其他回答
不,他们没有排队,他们在睡觉
表单的锁语句
lock (x) ...
其中x是引用类型的表达式,精确地等价于
var temp = x;
System.Threading.Monitor.Enter(temp);
try { ... }
finally { System.Threading.Monitor.Exit(temp); }
你只需要知道它们在等待彼此,只有一个线程会进入锁块,其他线程会等待…
Monitor是完全用。net编写的,所以足够快,还可以查看带有reflector的Monitor类了解更多细节
锁语句中的部分只能由一个线程执行,因此所有其他线程将无限期地等待持有锁的线程完成。这可能导致所谓的死锁。
lock语句被转换为对Monitor的Enter和Exit方法的调用。
lock语句将无限期地等待锁定对象被释放。
对性能的影响取决于锁定的方式。你可以在这里找到一个很好的优化列表:http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/
基本上,您应该尽可能少地尝试锁定,因为它会使等待代码进入睡眠状态。如果你在一个锁中有一些繁重的计算或长时间的代码(例如文件上传),它会导致巨大的性能损失。
根据微软的MSDN,这个锁相当于:
object __lockObj = x;
bool __lockWasTaken = false;
try
{
System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
// Your code...
}
finally
{
if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
}
如果需要在运行时创建锁,可以使用开源的DynaLock。您可以在运行时创建新锁,并使用上下文概念指定锁的边界。
DynaLock是开源的,源代码可以在GitHub上获得