Is locking on the requested object a bad idea?
- by Quick Joe Smith
Most advice on thread safety involves some variation of the following pattern:
public class Thing
{
private static readonly object padlock = new object();
private string stuff, andNonsense;
public string Stuff
{
get
{
lock (Thing.padlock)
{
if (this.stuff == null)
this.stuff = "Threadsafe!";
}
return this.stuff;
}
}
public string AndNonsense
{
get
{
lock (Thing.padlock)
{
if (this.andNonsense == null)
this.andNonsense = "Also threadsafe!";
}
return this.andNonsense;
}
}
// Rest of class...
}
In cases where the get operations are expensive and unrelated, a single locking object is unsuitable because a call to Stuff would block all calls to AndNonsense, degrading performance. And rather than create a lock object for each call, wouldn't it be better to acquire the lock on the member itself (assuming it is not something that implements SyncRoot or somesuch for that purpose? For example:
public string Stuff
{
get
{
lock (this.stuff)
{
// Pretend that this is a very expensive operation.
if (this.stuff == null)
this.stuff = "Still threadsafe and good?";
}
return this.stuff;
}
}
Strangely, I have never seen this approach recommended or warned against. Am I missing something obvious?