在我的应用程序中,我有一个启动同步过程的表单,出于多种原因,我希望一次只允许一个同步运行。所以我在我的表单中添加了一个静态bool字段,指示是否正在进行同步,并添加了一个锁定,如果尚未设置此字段,则将该字段设置为true,以便第一个线程可以启动同步,但是当它运行其他每个线程时将尝试启动它将终止。
我的代码是这样的:
internal partial class SynchronizationForm : Form
{
private static volatile bool workInProgress;
private void SynchronizationForm_Shown(object sender, EventArgs e)
{
lock (typeof(SynchronizationForm))
{
if (!workInProgress)
{
workInProgress = true;
}
else
{
this.Close();
}
}
}
}
这很好用,但是当我在项目上运行Code Analysis时,我收到以下警告信息:
CA2002:Microsoft.Reliability:'SynchronizationForm.SynchronizationForm_Shown(object,EventArgs)'锁定类型为'Type'的引用。将其替换为具有强身份的对象的锁定。
任何人都可以向我解释我的代码有什么问题,如何改进它以使警告消失。对象具有强烈的同一性意味着什么?
答案 0 :(得分:9)
有什么问题是你锁定了一些公共的(typeof(SynchronizationForm)
),它可以在你的代码中随处访问,如果某个其他线程锁定同一件事,你就会遇到死锁。一般来说,最好只锁定私有静态对象:
private static object _syncRoot = new object();
...
lock (_syncRoot)
{
}
这可以保证只有SynchronizationForm
可以拥有锁。
答案 1 :(得分:6)
来自MSDN explanation of the rule
当一个对象可以跨应用程序域边界直接访问时,它被认为具有弱标识。尝试获取具有弱标识的对象的锁的线程可以被另一个具有锁定在同一对象的应用程序域中的第二个线程阻止。
由于您无法预测另一个AppDomain可能会采取什么锁定,并且由于此类锁定可能需要进行编组,然后会很昂贵,因此这条规则对我来说很有意义。
答案 2 :(得分:3)
问题是typeof(SynchronizationForm)不是私有锁对象,这意味着任何其他代码都可以使用它来锁定,这可能导致死锁。例如,如果其他一些代码执行此操作:
var form = new SynchronizationForm();
lock(typeof(SynchronizationForm))
{
form.SomeMethodThatCausesSynchronizationForm_ShownToBeCalled();
}
然后会发生死锁。相反,你应该在SynchronizationForm类中对一个私有锁对象进行delcare,并锁定它。
答案 3 :(得分:2)
类的
System.Type
对象可以方便地用作类的静态方法的互斥锁。
来源:http://msdn.microsoft.com/en-us/library/aa664735(VS.71).aspx
为了增加Doug的答案,你在这里有一个锁定机制,它只能在静态方法中使用,在实例方法中使用。