多个文本说,当在.NET中实现双重检查锁定时,您锁定的字段应该应用volatile修饰符.但为什么呢?考虑以下示例:
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
Run Code Online (Sandbox Code Playgroud)
为什么不"锁定(syncRoot)"完成必要的内存一致性?在"lock"语句之后,读取和写入都是不稳定的,因此必须实现必要的一致性,这不是真的吗?
我在C#中有一个函数,可以从多个线程多次调用,我希望它只能完成一次,所以我想到了这个:
class MyClass
{
bool done = false;
public void DoSomething()
{
lock(this)
if(!done)
{
done = true;
_DoSomething();
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题是_DoSomething需要很长时间,我不希望很多线程等待它,只要他们可以看到这done是真的.
这样的事情可以解决方法:
class MyClass
{
bool done = false;
public void DoSomething()
{
bool doIt = false;
lock(this)
if(!done)
doIt = done = true;
if(doIt)
_DoSomething();
}
}
Run Code Online (Sandbox Code Playgroud)
但只需手动锁定和解锁就会好得多.
我怎样才能手动锁定和解锁lock(object)?我需要它使用相同的接口,lock因此这种手动方式lock将相互阻塞(对于更复杂的情况).
请考虑以下代码:
public class Foo
{
private static object _lock = new object();
public void NameDoesNotMatter()
{
if( SomeDataDoesNotExist() )
{
lock(_lock)
{
if( SomeDataDoesNotExist() )
{
CreateSomeData();
}
else
{
// someone else also noticed the lack of data. We
// both contended for the lock. The other guy won
// and created the data, so we no longer need to.
// But once he got out of the lock, we got in.
// There's nothing left to do.
} …Run Code Online (Sandbox Code Playgroud)