C# Lock syntax - 2 questions

后端 未结 3 609
醉梦人生
醉梦人生 2020-12-21 09:00

Can I use string as locker in the Lock ?

lock(\"something\")

Can I do lock without braces if its only one line ?

lock(\"som         


        
相关标签:
3条回答
  • 2020-12-21 09:13

    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.

    0 讨论(0)
  • 2020-12-21 09:23

    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.

    0 讨论(0)
  • 2020-12-21 09:26

    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.

    0 讨论(0)
提交回复
热议问题