C#Lock语法 - 2个问题

时间:2011-08-04 06:55:31

标签: c# .net multithreading locking

我可以在锁中使用字符串作为锁定器吗?

lock("something")

如果只有一行,我可以不用大括号锁定吗?

lock("something") foo();

3 个答案:

答案 0 :(得分:10)

1)是的,字符串(通常)被实习(默认,感谢@Eric),因此同一"something"的任何实例都会指向同一个对象,因此你'好的这是非常不好的做法,因为其他人,例如,在另一个库中,可以锁定你的字符串,从而有可能造成死锁。请看这里:{{3 }}

你应该这样做:

private static readonly object mutex = new object();

lock(mutex)
{
    //....
}

2)是的,与所有陈述相同。你有的任何地方:

{
    // One line
}

可能只是

// One line

*几乎任何事情,请参阅@LukeH的catch块的示例,它需要括号。

答案 1 :(得分:6)

是的,你可以使用字符串实例作为锁的目标。但是,有一些非常奇怪的边缘情况需要考虑。

案例1: Literal vs. StringBuilder

在以下示例中,两个锁将不使用相同的字符串实例。这是因为文字是实习的,但是构建的实例不是。

string a = "something";
string b = new StringBuilder().Append("some").Append("thing").ToString();

// These are different.
lock (a)
lock (b)

但是,我们可以手动实习字符串。

// These are the same.
lock (a)
lock (String.Intern(b))

案例2:版本注意事项

空字符串从版本到版本的插入方式存在一些差异。

string a = String.Empty;
string b = new StringBuilder().Append(String.Empty);

// These are the same in 1.0, 1.1, 3.5, and 4.0.
// These are different in 2.0 and 3.0.
lock (a);
lock (String.Intern(b))

案例3:实施差异

Microsoft的CLI实现并不是唯一的。可以想象,不同的实现表现出不同的行为,并有各自的警告。

案例4: CompilationRelaxations.NoStringInterning

取决于程序集是否用此装饰以及CLR是否实际使用它(而不是忽略它)可能会改变实习机制的行为。这是一个特别有害的问题,因为它可能意味着相同的代码根据其运行的上下文而表现不同。


我确信还有其他一些我不知道的边缘情况。但是,重点是依赖字符串实例进行锁定(或任何需要隐式假设其引用等价的目的)是危险的。

答案 2 :(得分:2)

乔治写的一切都是正确的。但有一个补充。无论如何你应该使用大括号来完全清楚你想要在大括号内运行什么。让你偶然写下类似的东西:

if(...)
    // one line
    // another line

在读取时你可能会在if块中执行这两行(某些示例使用identation来定义块)。如果你改为写

if(...)
{
    // one line
}
// another line

很清楚if块中运行的是什么,什么不是。