Reputation: 55
If I have two shared resources,these resources are updated in their own separate tasks that run concurrently. The second task checks on the status of the shared resource from the first task and then updates it's own shared resource. After one of the tasks completes I then check the status of both shared resources. Do I need two separate locks to make this thread safe or is one enough? For example:
private void example()
{
object lockObj = new object();
int x = 0;
int y =0;
List<Task> tasks = new List<Task>();
Task task1 = Task.Factory.StartNew(() =>
{
try
{
int z = doComputation()
resultofComputation = z;
}
catch
{
resultofComputation=-1;
}
finally
{
lock(lockObj)
{
x = resultofComputation;
}
}
}
tasks.Add(workTask);
Task task2 = Task.Factory.StartNew(() =>
{
try
{
checkOnstatusofThing(ref x);
lock(lockObj)
{
y +=x;
}
}
finally
{
}
}
Task.WaitAny(tasks.ToArray());
if(x =3 || y ==9)
{
return -1;
}
return 0;
}
checkOnstatusofThing(ref int x)
{
if(x == 5)
{
return;
}
}
Upvotes: 1
Views: 106
Reputation: 43475
Using a single lock object is the safe option. You define the variables that consist the shared state, and meticulously use the lock every time you write and read these variables, from any thread. If you do this, then the correctness of your application will be easy to prove (easy by the standards of multithreading, which is inherently difficult).
To minimize the contention for the lock you should release it as fast as possible. You should avoid doing anything that is not related with the shared state while holding the lock. For example if you must call a method with a shared variable as argument, take a snapshot of the variable, and use the snapshot as argument.
int snapshot;
lock (lockObj)
{
snapshot = sharedState;
}
MethodCall(snapshot);
If you follow this advice then the contention for the lock should be minimal, and should not affect significantly the performance of your application. But if your benchmarks reveal that there is too much contention for the lock, then you may consider introducing multiple locks to increase the granularity of the locking scheme and reduce the contention. Be aware that this change will increase the complexity of your application by a magnitude. Deadlocks will become possible, so you must be familiar with the classical synchronization problems like the Five Dining philosophers, and their solutions.
Upvotes: 1