Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#锁定单行(if语句)_C#_.net_Multithreading_If Statement_Locking - Fatal编程技术网

C#锁定单行(if语句)

C#锁定单行(if语句),c#,.net,multithreading,if-statement,locking,C#,.net,Multithreading,If Statement,Locking,此代码是否仅锁定在if语句上,还是锁定两行代码 lock (LockObject) if (instance == null) instance = Instance(); 它锁定了所有的代码。这里省略了{和}forif。if语句包括一个用于“then”情况的语句。因此,锁适用于两条线路 一个简单的经验法则是:如果有一个{,它将一直应用到匹配的},否则它将一直应用到第一个。这并不是涵盖所有情况,但肯定是最常见的情况。它锁定了整个语句。考虑下面的例子: lock (Lo

此代码是否仅锁定在
if
语句上,还是锁定两行代码

lock (LockObject)
    if (instance == null)
        instance = Instance();

它锁定了所有的代码。这里省略了
{
}
for
if

if语句包括一个用于“then”情况的语句。因此,锁适用于两条线路


一个简单的经验法则是:如果有一个
{
,它将一直应用到匹配的
}
,否则它将一直应用到第一个
。这并不是涵盖所有情况,但肯定是最常见的情况。

它锁定了整个语句。考虑下面的例子:

 lock (LockObject)
 {
     if (instance == null) {
 }

如果在使用大括号时仅锁定
If
条件,则由于未正确排列/匹配,将导致编译器错误

lock
锁定整个块。因为它后面没有大括号(
{}
),所以它锁定了一个隐式块--
if
语句。这里,同样的逻辑适用于-
if
在满足条件时执行块。因为它后面也没有大括号,所以它隐式地有一个包含单个语句的块。换句话说,给定代码相当于:

lock (LockObject) {
    if (instance == null) {
        instance = Instance();
    }
}

此代码段正在锁定两行代码

在if语句完成执行之前,不会释放LockObject上的锁。这意味着,如果第2行中的条件为真,那么它将在释放第1行中的锁之前执行第3行


希望有帮助:)

锁被C编译器翻译成
监视器。输入
监视器。退出
。这是C代码

给出下面的IL代码,它清楚地显示在分配了
实例
(L_0026)后调用了
监视器.Exit
(L_0036)

两行代码都已锁定

.method private hidebysig static void Main(string[] args) cil managed
{
  .entrypoint
  .maxstack 2
  .locals init (
    [0] bool flag,
    [1] object obj2,
    [2] bool flag2)
  L_0000: nop
  L_0001: ldc.i4.0
  L_0002: stloc.0
  L_0003: ldsfld object TestLock.Program::LockObject
  L_0008: dup
  L_0009: stloc.1
  L_000a: ldloca.s flag
  L_000c: call void [mscorlib]System.Threading.Monitor::Enter(object, bool&)
  L_0011: nop
  L_0012: ldsfld object TestLock.Program::instance
  L_0017: ldnull
  L_0018: ceq
  L_001a: ldc.i4.0
  L_001b: ceq
  L_001d: stloc.2
  L_001e: ldloc.2
  L_001f: brtrue.s L_002b
  L_0021: call object TestLock.Program::Instance()
  L_0026: stsfld object TestLock.Program::instance
  L_002b: leave.s L_003d
  L_002d: ldloc.0
  L_002e: ldc.i4.0
  L_002f: ceq
  L_0031: stloc.2
  L_0032: ldloc.2
  L_0033: brtrue.s L_003c
  L_0035: ldloc.1
  L_0036: call void [mscorlib]System.Threading.Monitor::Exit(object)
  L_003b: nop
  L_003c: endfinally
  L_003d: nop
  L_003e: ldsfld object TestLock.Program::instance
  L_0043: ldnull
  L_0044: ceq
  L_0046: call void [mscorlib]System.Console::WriteLine(bool)
  L_004b: nop
  L_004c: ret
  .try L_0003 to L_002d finally handler L_002d to L_003d
}

如果不能单独执行
语句,则表达式的
true
-情况需要在语句后面加块,因此,@Mureinik已经说过,
lock
锁定整个初始化块。你甚至可以这样写:

lock (LockObject) if (instance == null) instance = Instance();
// field in class
Lazy<Instance> lazyInstance = new Lazy<Instance>(() => Instance());

//usage in code
var instanceValue = lazyInstance.Value;
但是,在这种情况下,不建议在没有大括号的情况下编写代码,因为这样会非常混乱,并且很难调试。还要注意,
lock
语句是类使用的语法糖,您的代码编译成:

try
{
    Monitor.Enter(LockObject);
    if (instance == null)
    {
        instance = Instance();
    }
}
finally
{
    Monitor.Exit(LockObject);
}
我想指出的是,对于初始化逻辑,您可以使用一个线程安全的类,它使用的结构不像
监视器
那么重,并且可以比您的代码执行得更快。代码如下所示:

lock (LockObject) if (instance == null) instance = Instance();
// field in class
Lazy<Instance> lazyInstance = new Lazy<Instance>(() => Instance());

//usage in code
var instanceValue = lazyInstance.Value;
//类中的字段
Lazy lazyInstance=new Lazy(()=>Instance());
//代码中的用法
var instanceValue=lazyInstance.Value;

由于缺少分号,目前它甚至无法编译。或者,您可以使用
Lazy
,它可以更清楚地显示您的意图,并且是线程安全的。