Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Locking method-scoped "string" object from different threads blocks execution?

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);
        }
    }
}
like image 458
Jack Avatar asked Dec 27 '22 22:12

Jack


2 Answers

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();)

like image 184
Kirk Woll Avatar answered Jan 04 '23 23:01

Kirk Woll


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.

like image 20
kevingessner Avatar answered Jan 05 '23 00:01

kevingessner