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);
}
}
}
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();
)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With