C# Lock syntax - 2 questions
Can I use string as locker in the Lock ?
lock("something")
Can I do lock without braces if its only one line ?开发者_Python百科
lock("something") foo();
1) Yes, strings are (generally) interned (by default, thanks @Eric), so any instance of the same "something"
would point to the same object, therefore you'd be ok. This is very bad practice though, because someone else, in another library for example, could lock on your string, thus giving the potential for deadlocks. See here: Using string as a lock to do thread synchronization
You should do this:
private static readonly object mutex = new object();
lock(mutex)
{
//....
}
2) Yes, same with all statements. Anything* where you have:
{
// One line
}
could just be
// One line
*Almost anything, see @LukeH's example of the catch
block, which requires the braces.
Yes, you could use a string instance as the target of a lock. However, there are some really weird edge cases to consider.
Case 1: Literal vs. StringBuilder
In the following example the two locks will not use the same string instance. This is because the literal is interned, but the built instance is not.
string a = "something";
string b = new StringBuilder().Append("some").Append("thing").ToString();
// These are different.
lock (a)
lock (b)
However, we could manually intern the strings.
// These are the same.
lock (a)
lock (String.Intern(b))
Case 2: Version considerations
There are some differences with the way empty strings are interned from version to version.
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))
Case 3: Implementation differences
Microsoft's implementation of the CLI is not the only one out there. It is conceivable that different implementations exhibit different behaviors and have their own set of caveats.
Case 4: CompilationRelaxations.NoStringInterning
Depending on whether assemblies are decorated with this and whether the CLR actually uses it (as opposed to ignoring it) may change the behavior of the interning mechanisms. This a particularly pernicious problem because it could mean that the same code behaves differently depending upon the context in which it was run.
I am sure there are other edge cases that I am unaware of. However, the point is that relying on string instances for locking purposes (or any purpose that requires implicit assumptions about the equivalence of their references) is dangerous.
Everything George is writing is correct. One addition though. You should use braces anyway to make it perfectly clear what you want to run inside the braces. Let say you by accident write something like:
if(...)
// one line
// another line
when reading that you might thing that both lines will be executed inside the if block (some example uses identation to define blocks). If you instead write
if(...)
{
// one line
}
// another line
it is perfectly clear what is run within the if block and what isn't.
精彩评论