lock()函数在c#中是如何工作的?
我有一些c#代码,看起来像这样:lock()函数在c#中是如何工作的?,c#,asp.net,locking,deadlock,C#,Asp.net,Locking,Deadlock,我有一些c#代码,看起来像这样: if (cache[filename] != null) { return (AppSettings)cache[filename]; } lock (thisLock) { using (StreamReader sr = new StreamReader(filename)) { instance = (AppSettings)serial.Deserialize(sr); cache.Insert(
if (cache[filename] != null) {
return (AppSettings)cache[filename];
}
lock (thisLock)
{
using (StreamReader sr = new StreamReader(filename))
{
instance = (AppSettings)serial.Deserialize(sr);
cache.Insert(filename, instance, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration);
}
}
return (AppSettings)cache[filename];
AppSettings result = null;
lock (thisLock)
{
if (cache[filename] != null) {
result = (AppSettings)cache[filename];
}
else
{
using (StreamReader sr = new StreamReader(filename))
{
instance = (AppSettings)serial.Deserialize(sr);
cache.Insert(filename, instance, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration);
}
result = (AppSettings)cache[filename];
}
}
return result;
因此,我对锁的理解是,一旦它被“解锁”,那么代码块将被执行。因此,对于上面的代码,我假设需要在锁代码块中进行另一次检查,以查看对象是否已经创建
另外,如何检查死锁?当另一个线程正在处理时,
lock
指令将阻止任何其他线程进入。您可以使用它来保护非线程安全的受保护资源
在您的例子中,字典缓存是您想要保护的,因为如果多个线程在其中添加、更改和删除元素,您的程序几乎肯定会崩溃
要保护缓存
,需要将整个操作包装在锁
语句中,如下所示:
if (cache[filename] != null) {
return (AppSettings)cache[filename];
}
lock (thisLock)
{
using (StreamReader sr = new StreamReader(filename))
{
instance = (AppSettings)serial.Deserialize(sr);
cache.Insert(filename, instance, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration);
}
}
return (AppSettings)cache[filename];
AppSettings result = null;
lock (thisLock)
{
if (cache[filename] != null) {
result = (AppSettings)cache[filename];
}
else
{
using (StreamReader sr = new StreamReader(filename))
{
instance = (AppSettings)serial.Deserialize(sr);
cache.Insert(filename, instance, null, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration);
}
result = (AppSettings)cache[filename];
}
}
return result;
因此,对于上面的代码,我假设需要在锁代码块中进行另一次检查,以查看对象是否已经创建
对。如果两个线程都检查并发现缓存项丢失,那么您只希望其中一个线程实际执行在缓存中创建该项的昂贵工作,而不是两个线程,因此您需要在锁内部再次应用相同的检查。这就是著名的“双重检查锁定”模式
另外,我如何检查死锁
我看到您的代码具有死锁的唯一方式是,如果其他线程持有要访问的文件上的锁,并且它正在等待锁
块中的某个线程执行它想要执行的其他操作。这将是一个僵局。如果您确保此代码是唯一可以访问该文件的代码,或者任何访问此文件的内容都不会依赖于此线程,那么(给定您显示的代码)您会没事的。可能重复请注意,您的代码仍然完全不安全。@SLaks缓存
对象是专门设计用于同时从多个线程操作的,因此一个线程可能正在读取一个值,而另一个线程正在写入该值这一事实不是问题(只要您不关心这些概念性操作发生的顺序)。在这里使用锁的唯一原因是避免使用多个线程读取文件(此代码正确执行),并且可能还避免在缓存未命中时多次读取文件(这一部分它没有做到,但可以很容易地修改来做到)。根据其文档,缓存
对象是专门设计来同时从多个线程进行操作的,因此OP的代码实际上是完全安全的。在这种情况下,我同意,没有必要保护它。