I have found out (the hard way) that actually locking with $ string is pretty bad, it does NOT work.
This is the code I used for testing:
object o = new object();
Parallel.For(0, 1000, (i) => {
lock (o) {
Console.WriteLine($"Hey {i}");
Thread.Sleep(5000);
}
});
It looks dumb because it is a silly test and what is expected happens: It locks the region correctly.
The following also works
var lid = "SomeId";
Parallel.For(0, 1000, (i) => {
lock(lid) {
Console.WriteLine($"Hey {i}");
Thread.Sleep(5000);
}
});
Parallel.For(0, 1000, (i) => {
lock("SomeId") {
Console.WriteLine($"Hey {i}");
Thread.Sleep(5000);
}
});
Now if you try to compose the string on the fly and use it as a locking mutex, it won't lock properly, it will generate many different instances of the same string and you'll get multiple different "locks" allowing different threads to access the resource.
This does not work
var lid = "SomeId";
Parallel.For(0, 1000, (i) => {
lock($"{lid}_LOCKING") {
Console.WriteLine($"Hey {i}");
Thread.Sleep(5000);
}
});
var lid = "SomeId";
Parallel.For(0, 1000, (i) => {
lock(lid + "_LOCKING") {
Console.WriteLine($"Hey {i}");
Thread.Sleep(5000);
}
});
The code below works, but I would avoid if the dynamic expression may generate way too many unique strings:
var lid = "SomeId";
Parallel.For(0, 1000, (i) => {
lock(String.Intern($"{lid}_LOCKING")) {
Console.WriteLine($"Hey {i}");
Thread.Sleep(5000);
}
});
I might have been lazy to test it this way before, but now I see it clearly it's a dumb way to lock. Do not lock with non-constant strings, even if the string components used in creating that string are immutable, it does not work;