好吧,我已经使用了很多锁,但我之前从未有过这种情况。我有两个不同的类,包含用于修改相同MSAccess数据库的代码:
public class DatabaseNinja
{
public void UseSQLKatana
{
//Code to execute queries against db.TableAwesome
}
}
public class DatabasePirate
{
public void UseSQLCutlass
{
//Code to execute queries against db.TableAwesome
}
}
这是一个问题,因为数据库的事务不能并行执行,并且这些方法(UseSQLKatana和UseSQLCutlass)由不同的线程调用。
在我的研究中,我发现使用公共对象作为锁定对象是不好的做法,那么如何锁定这些方法以使它们不会串联运行?答案只是将这些方法放在同一个类中吗? (在我的真实代码中,这实际上并不那么简单)
答案 0 :(得分:16)
嗯,首先,您可以创建第三个类:
internal class ImplementationDetail
{
private static readonly object lockme = new object();
public static void DoDatabaseQuery(whatever)
{
lock(lockme)
ReallyDoQuery(whatever);
}
}
现在UseSQLKatana和UseSQLCutlass调用ImplementationDetail.DoDatabaseQuery。
其次,您可以决定不担心它,并锁定两种类型都可见的对象。避免这种情况的主要原因是因为很难推断谁正在锁定对象,并且难以防止恶意部分信任的恶意代码锁定对象。如果您不关心任何一个缺点,那么您不必盲目遵循指南。
答案 1 :(得分:8)
锁定公共对象的不良做法是,您永远无法确定ELSE是谁锁定该对象。虽然不太可能,但有一天其他人可以决定他们想要获取你的锁对象,并做一些最终调用你的代码的进程,你锁定到同一个锁对象,现在你有一个不可能的死锁来搞清楚。 (使用'this'也是同样的问题。)
更好的方法是使用公共Mutex对象。这些更重要,但调试问题要容易得多。
答案 2 :(得分:2)
使用Mutex
。
您可以在主类中创建互斥锁,并在每个类的开头调用Wait方法(方法);然后设置互斥,所以当调用另一个方法时,它将等待第一堂课完成
啊,记得发布退出这些方法的互斥...
答案 3 :(得分:0)
您可以使用公共LOCK对象作为锁定对象。您只需指定您正在创建的对象是一个仅用于锁定Ninja和Pirate类的Lock对象。
答案 4 :(得分:0)
我在这里看到两个不同的问题:
为什么lock
对公共对象不好?
我们的想法是,在维护lock
时锁定对象会限制访问 - 这意味着无法访问其成员,并且其他来源可能无法识别lock
并尝试利用实例,甚至尝试自己获取lock
,从而导致问题。
出于这个原因,请使用专用对象实例锁定。
如何锁定这些方法以使它们不会串联运行?
你可以考虑Mutex
类;创建“全局”互斥锁将允许您的类在知道整个应用程序中的锁状态的基础上运行。或者,您可以使用共享的ReaderWriterLockSlim
实例,但我不会真正推荐跨类共享它。