两个对象必须有两个锁吗?
Is it necessary to have two locks for two objects?
如果我有两个共享资源,这些资源会在 运行 各自独立的任务中同时更新。第二个任务检查第一个任务共享资源的状态,然后更新它自己的共享资源。其中一项任务完成后,我会检查两个共享资源的状态。我需要两个单独的锁来确保线程安全还是一个就足够了?例如:
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;
}
}
使用单个锁对象是安全的选择。你定义了组成共享状态的变量,并且小心翼翼地使用锁 every time you write and read these variables, from 任何 线程。如果你这样做,那么你的应用程序的正确性将很容易证明(按照多线程的标准很容易,这本来就很困难)。
为了尽量减少对锁的争用,您应该尽快释放它。你应该避免在持有锁的同时做任何与共享状态无关的事情。例如,如果您必须调用一个以共享变量作为参数的方法,拍摄该变量的快照,并将快照用作参数。
int snapshot;
lock (lockObj)
{
snapshot = sharedState;
}
MethodCall(snapshot);
如果您遵循此建议,那么对锁的争用应该是最小的,并且应该不会显着影响您的应用程序的性能。但是如果你的基准测试显示锁竞争太多,那么你可以考虑引入多个锁来增加锁定方案的粒度并减少竞争。请注意,此更改会大大增加应用程序的复杂性。死锁将成为可能,因此您必须熟悉 Five Dining philosophers 等经典同步问题及其解决方案。
如果我有两个共享资源,这些资源会在 运行 各自独立的任务中同时更新。第二个任务检查第一个任务共享资源的状态,然后更新它自己的共享资源。其中一项任务完成后,我会检查两个共享资源的状态。我需要两个单独的锁来确保线程安全还是一个就足够了?例如:
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;
}
}
使用单个锁对象是安全的选择。你定义了组成共享状态的变量,并且小心翼翼地使用锁 every time you write and read these variables, from 任何 线程。如果你这样做,那么你的应用程序的正确性将很容易证明(按照多线程的标准很容易,这本来就很困难)。
为了尽量减少对锁的争用,您应该尽快释放它。你应该避免在持有锁的同时做任何与共享状态无关的事情。例如,如果您必须调用一个以共享变量作为参数的方法,拍摄该变量的快照,并将快照用作参数。
int snapshot;
lock (lockObj)
{
snapshot = sharedState;
}
MethodCall(snapshot);
如果您遵循此建议,那么对锁的争用应该是最小的,并且应该不会显着影响您的应用程序的性能。但是如果你的基准测试显示锁竞争太多,那么你可以考虑引入多个锁来增加锁定方案的粒度并减少竞争。请注意,此更改会大大增加应用程序的复杂性。死锁将成为可能,因此您必须熟悉 Five Dining philosophers 等经典同步问题及其解决方案。