C# doesn\'t allow locking on a null value. I suppose I could check whether the value is null or not before I lock it, but because I haven\'t locked it another thread could c
First part of your question is already answered but I would like to add something for second part of your question.
It is simpler to use a different object to perform the locking, specially in this condition. This also resolve the issue to maintain the states of multiple shared objects in a critical section, e.g. list of employee and list of employee photos.
Moreover this technique is also useful when you have to acquire lock on primitive types e.g int or decimal etc.
In my opinion if you are use this technique as everybody else suggested then you don't need to perform null check twice. e.g. in accepted answer Cris has used if condition twice which really doesn't make any difference because the locked object is different then what is actually being modified, if you are locking on a different object then performing the first null check is useless and waste of cpu.
I would suggest the following piece of code;
object readonly syncRootEmployee = new object();
List employeeList = null;
List employeePhotoList = null;
public void AddEmployee(Employee employee, List photos)
{
lock (syncRootEmployee)
{
if (employeeList == null)
{
employeeList = new List();
}
if (employeePhotoList == null)
{
employeePhotoList = new List();
}
employeeList.Add(employee);
foreach(EmployeePhoto ep in photos)
{
employeePhotoList.Add(ep);
}
}
}
I can't see any race condition in here if anybody else see race condition please do respond in comments. As you can see in above code it resolve 3 problem at once, one no null check required before locking, second it creates a critical section without locking two shared sources, and third locking more than one object cause deadlocks due to lack of attention while writing code.
Following is how I use the locks on primitive types.
object readonly syncRootIteration = new object();
long iterationCount = 0;
long iterationTimeMs = 0;
public void IncrementIterationCount(long timeTook)
{
lock (syncRootIteration)
{
iterationCount++;
iterationTimeMs = timeTook;
}
}
public long GetIterationAvgTimeMs()
{
long result = 0;
//if read without lock the result might not be accurate
lock (syncRootIteration)
{
if (this.iterationCount > 0)
{
result = this.iterationTimeMs / this.iterationCount;
}
}
return result;
}
Happy threading :)