鉴于以下要求,有人可以发布一个非常简单的代码示例,说明如何使用多线程,同时正确利用锁来保持共享数据“安全”吗?
假设您将整数x声明为100.然后,您希望生成10个线程,每个线程执行一些操作。当每个线程完成操作时,它会递减x。我知道你可以使用互锁,但是在评估条件时你不需要锁定吗?换句话说,在执行操作之前,您需要确保x大于0.
答案 0 :(得分:4)
您可以使用x
关键字将lock
的每次访问权限包括在内:
private object xLock = new object();
...
lock (xLock)
{
// Any read or write access to x
}
这将确保对x的所有访问都是原子的,并且没有与线程安全相关的危险。
答案 1 :(得分:4)
如果要编写简单的多线程程序,请考虑在C#4.0中使用并行扩展。
具有锁和可变共享数据的普通多线程程序从不简单。
答案 2 :(得分:2)
你可能不希望在操作完成后递减计数器,因为计数器可能是1,所有10个线程都会检查它,看它大于零,并开始执行操作,只对所有递减它完成了。
您可以使用Interlocked.Decrement递减计数器并在执行操作之前检查其值而不锁定:
int temp = Interlocked.Decrement(x);
if(temp >= 0) //temp is the decremented value
{
//perform action
}
答案 3 :(得分:2)
您想使用Interlocked.CompareExchange。假设您要修改名为Counter
的共享变量。
int count = Counter;
if (count == 0)
return;
if (Interlocked.CompareExchange(ref Counter, count-1, count) == count)
{
// Counter was decremented.
// perform your processing.
}
如果您希望线程在退出之前处理最多10个项目,则可以将其包装在循环中。
请注意,计数器控制条目到处理方法。也就是说,逻辑上它的工作原理如下:
if (counter > 0)
{
--counter;
DoAction();
}
您的问题似乎要求提供类似的内容:
if (counter > 0)
{
DoAction();
--counter;
}
但是如果你以这种方式编码,那么你可能会调用DoAction
超过100次(或者counter
的初始值是什么),因为其他线程可以在最后一次之前启动操作一个已经完成。
答案 4 :(得分:0)
如果你想做你的版本的东西,只需实现自己的逻辑
lock(somecommonreference)
{
if (x>0) x--;
}