![](/img/trans.png)
[英]What are the differences between various threading synchronization options in C#?
[英]C# threading and synchronization
我有一个私有静态字段,我用它来进行同步(锁定)。 现在我有两个函数,我不想同时执行。 所以我这样做了:
public class Synchronization
{
private static object _lock = new object();
public void MethodA()
{
lock (_lock)
{
Console.WriteLine("I shouldn't execute with MethodB");
}
}
public void MethodB()
{
lock (_lock)
{
Console.WriteLine("I shouldn't execute with MethodA");
}
}
}
我知道锁定一个对象会阻止单个函数的并行执行,但如果我在同时运行的不同方法中使用相同的锁对象,那么同样的工作吗? 简单地说,put可以让任何其他线程获取锁定另一个函数中已经锁定的对象吗?
一次只有一个线程可以获取锁,因此该状态对于单个锁实例上的所有线程都是独占的。 因此,在您的示例中,由于您的锁是静态的,因此在Synchronization
类的所有实例的任何给定时间只能执行一个方法体。 如果要锁定每个类的实例,请不要将锁定对象标记为静态。
您对同步的假设是正确的。
请注意,您应该标记锁定对象readonly
一个完全不透水的解决方案。 正如代码所代表的那样,可以重新分配锁定对象,从而打破锁定语义,例如:
public class Synchronization
{
private static object _lock = new object();
public void MethodA()
{
lock (_lock)
{
Console.WriteLine("I shouldn't execute with MethodB");
}
}
public void MethodB()
{
//This shouldn't be allowed!
_lock = new object();
lock (_lock)
{
Console.WriteLine("I shouldn't execute with MethodA");
}
}
}
锁定对象应标记为readonly
,即:
private static readonly object _lock = new object();
我相信你正确阅读MSDN上的锁定声明 。
你正确地做到了。 您创建了两个不会同时输入的关键部分。
因此,MethodA和MethodB不会同时处于“活动状态”。 此外,只有一个MethodA(和MethodB)同时处于活动状态。
这适用于您创建的所有对象。 我的意思是:任何MethodA或MethodB中只有一个线程来自任何对象。 如果希望锁仅在一个对象中发生,则可以使_lock对象不是静态的。
根据作为锁定目标的对象而不是lock
语句发生的方法授予lock
。 因此,在您的情况下,多个线程可能会输入各种方法,但一次只有一个线程可以执行lock
语句中的任何代码。
首先, _lock
不应该是静态的。 或者您希望对象的多个实例彼此锁定自己? 其次,您应该在类中只有一个synchronized方法。 更重要的是,您应该避免类中同步方法之间的依赖关系。 否则,您将面临风险,即您的方法的调用者会做错并且会出现意外行为。
例如,考虑以下代码:
class Synchronized
{
object lockObj = new object();
int counter = 100;
public void Decrement()
{
lock (this.lockObj)
{
this.counter--;
}
}
public int IsZero()
{
lock (this.lockObj)
{
return this.counter == 0;
}
}
}
现在用共享的同步实例做什么?
像这样使用它
while (!synchronized.IsZero())
{
synchronized.Decrement();
}
现在线程1调用Decrement,计数器变为0并且线程2立即调用Decrement,因为它在Decrement方法中等待锁定,而不是IsZero方法。 计数器现在为-1,循环无限。
并不是锁定机制编程错误,而是调用者没有很好地使用它。 如果你只在Synchronized类上暴露了一个同步方法,你就不会愚弄程序员盲目地相信它是安全的。
它应该是这样的:
class Synchronized
{
object lockObj = new object();
int counter = 100;
public bool IfNotZeroDecrement()
{
lock (this.lockObj)
{
if (this.counter > 0)
this.counter--;
return this.counter > 0;
}
}
}
/// Usage:
while (synchronized.IfZeroDecrement())
{
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.