因此,我有一个基类,它有一个私有锁定对象,如下所示:
class A
{
private object mLock = new object();
public virtual void myMethod()
{
lock(mLock)
{
// CS
}
}
}这个锁定对象用于A的大多数操作.因为它们需要线程安全。
现在,假设我是这样从A继承的:
class B : public A
{
public override void myMethod()
{
lock(???)
{
// CS of mymethod here
// Call base (thread safe alread)
base.myMethod();
}
}
}使B线程安全的约定是什么?B是否也应该像A那样拥有一个私有锁定对象?如果我需要像上面那样调用基本方法呢?
我想我只是好奇在基类已经线程安全的情况下,使子类线程安全的约定是什么。谢谢!
编辑:有些人问我所谓的“线程安全”是什么意思.我要澄清的是,我试图通过互斥来实现线程安全.一次只应该执行一个线程,这可能会改变对象的状态。
发布于 2010-06-29 16:54:08
您可能会公开A使用的锁:
protected object SyncLock { get { return mLock; } }如果B有自己的锁对象,则很容易得到以下结果:
由于锁在.NET中是递归的(无论是好的还是坏的),如果您的重写锁与A的实现相同,那么调用base.myMethod并递归地获取/释放锁是很好的。
说了这些之后,我渴望使大多数类非线程安全或不可变(只有与线程有关的类需要线程知识),而且大多数类不需要为继承而设计。
发布于 2010-06-29 16:55:08
这要看情况了。如果您的子类只使用来自基类的安全方法,并且没有添加任何额外的不安全状态,那么您就不必做任何事情(首选)。如果它添加了一些与基类状态无关的额外状态,那么您可以在子类中创建一个单独的锁对象并使用它。另一方面,如果需要确保以某种“事务性”方式更改基类中的新状态和状态,那么我将保护基类中的lock对象并使用它。
发布于 2010-06-29 16:59:45
没有足够的信息来回答你的问题,但首先要做的是。
仅使用lock 块并不能使代码线程安全.。
您在A中所做的一切就是让一个以上的线程一次不可能调用包含在lock(mLock)中的任何函数。线程安全是一个宽泛的术语,防止并发调用只是一个方面(并不总是您想要或需要的)。如果这是你所需要的,那么你显然已经采取了正确的方法。确定一下就行。
第二,您需要向子类公开的内容在上面的代码中并不明显。有三种情况:
B可能会调用protected (或者,如果它与A位于同一个程序集中),则在A上调用不包含在lock(mLock)中的函数,blocksB只调用包含在lock(mLock)块中的A函数,并且不提供任何需要您阻止并发callsB的操作,只调用包含在lock(mLock)块中的A上的函数,并且提供自己的操作,这些操作要求您防止并发调用。H 227G 228这实际上归结为两个不相关的问题:
protected)?
B将以一种需要保护的方式与A交互(换句话说,以一种已经不是A的方式公开需要保护的功能,如果是的话,它们应该使用相同的锁定对象吗?)
如果1) true of 2)是true,并且它们应该使用相同的锁定对象,那么您将需要通过protected属性公开锁定对象,并在所有锁中使用它(我建议在A中也使用它以提高可读性)。
如果两者都不是真的,那就别担心。如果2)为真,但它们不需要使用相同的锁定对象(换句话说,对A和B进行并发调用是可以接受的),那么不必担心公开锁定对象。请记住,B对A上受lock(mLock)保护的函数进行的任何调用都会锁定该对象,而不管外部锁是什么。
https://stackoverflow.com/questions/3142850
复制相似问题