4

I was just doing some random testing on locking in multi-threading this morning and strangely I found that locking a private "string" in two separate instance actually blocks the other thread from executing. Please find the code below for reference.

The thing that confuses me is that "string" in two objects are really two separate object, so why locking on one blocks the other? ( Note, if you replace string with other reference type object like List, it will not block the other thread from executing, which is really what we expected... )

class Program {
    static void Main(string[] args) {
        Thread th = new Thread(DoWork);
        th.Start();

        Thread th2 = new Thread(DoWork);
        th2.Start();
    }

    static void DoWork() {
        Test importer = new Test();
        importer.SyncTest();
    }



}

public class Test {
    public void SyncTest() {
        string find = "test";
        lock(find) {                
            Console.WriteLine("thread starting...");
            Thread.Sleep(4000);
        }
    }
}
2
  • I would reject this code if I saw it outside of a "test"... but it's an interesting peculiarity of string literals being explored. Commented Jun 22, 2012 at 1:52
  • Same here...Thanks for making the question clearer. ^^ Commented Jun 22, 2012 at 2:15

3 Answers 3

6

String constants are "interned". This means that when you type:

var s1 = "foo";
var s2 = "foo";

Both are the same instance of the string "foo". Likewise, it's the same instance when you invoke a method with a similarly defined local variable twice from different threads. This is done for performance reasons.

This is a special case, but on the other hand, you really should not be locking on strings. (I've yet to see a situation where the idomatic solution of creating a new lock object is not the way to go -- private object lockObject = new object();)

Sign up to request clarification or add additional context in comments.

1 Comment

+1 for creating a new private object for locking - it's really the only way to go
2

Literal strings in .NET are interned, so every time you use the same literal string, you're actually using the exact same object. Thus, both of your threads that reference "test" are referencing (and locking) the same object.

Creating a new List or other type gives you a new object, so each thread locks its own object.

Comments

2

It blocks when you use a string because all of your Test classes use the same string instance. C# will intern all string literals to conserve memory. So that is only once instance of the string "test".

The common language runtime conserves string storage by maintaining a table, called the intern pool, that contains a single reference to each unique literal string declared or created programmatically in your program. Consequently, an instance of a literal string with a particular value only exists once in the system.

So all instance of Test are using the same object to lock.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.