In addition to what Marc said, in real life people ofren try to lock on strings that might not be interned, such as locking on some key from the database record. Locking on strings only (kind of) works if you lock on interned string. But consider this:
// not interned, but both strings represent "test"
string lock1 = new string(new char[] { 't', 'e', 's', 't' });
string lock2 = new string(new char[] { 't', 'e', 's', 't' });
Task.Run(() =>
{
lock (lock1) {
Console.WriteLine("1 entered");
Thread.Sleep(1000);
}
});
Task.Run(() =>
{
lock (lock2)
{
Console.WriteLine("2 entered");
Thread.Sleep(1000);
}
});
This code immediately executes both "protected" sections, because despite of both strings are "test" - they are different instances. So locking on constant string is danregrous because it's global and you never know which else code uses such "lock", and locking on string variable is dangerous because it might just not work at all.
To answer a comment about locking on ReadyCount.ToString()
. That's exactly how people try to do this in real life (where ReadyCount
is some property of database record or similar). I guess by ReadyCount
you mean some number, not really a string (otherwise calling ToString
makes no sense). And no, this is also bad, because:
int readyCount = 1;
string lock1 = readyCount.ToString();
string lock2 = readyCount.ToString();
bool same = Object.ReferenceEquals(lock1, lock2);
// nope, not the same, lock will not work