设计问题。我知道此方法是线程安全的,但是从设计的角度来看,还有更好的方法吗?
我有一个抽象类(不是线程安全的):
public abstract class Class1
{
protected someobject myobject;
public Class1()
{
myobject = new someoject();
}
public virtual void proc1()
{
// do something with my object
}
public virtual void proc2()
{
// do something with my object
}
public virtual void proc3()
{
// do something with my object
}
}
现在,我想从此类创建一个需要线程安全的后代,所以我这样做:
public class Class2: Class1
{
private static readonly object obj = new object();
public override void proc1()
{
lock(obj)
{
base.proc1();
}
}
public override void proc2()
{
lock(obj)
{
base.proc2();
}
}
public override void proc3()
{
lock(obj)
{
base.proc3();
}
}
}
我可以使基本线程安全,但是我还有其他一些从同一基本继承的类,不需要线程安全,因此我不想强加线程安全。这种设计有什么问题吗?如果基地有很多公众成员,这有点乏味。
答案 0 :(得分:2)
很难推断出代码的潜在用途,但从一般考虑的角度来看,我将重点介绍以下问题:
Class2
代码,发现除了基类方法的竞争条件保护外,它与基类相比没有任何其他增加。通常,我们倾向于针对特定状态施加线程安全性,以确保并发访问条件下状态的一致性。但是在这种情况下,Class2
根本不知道它所保护的行为是否会导致比赛状态。如果在不再需要线程安全的情况下以Class1
的方式进行修改,该怎么办-我们将在Class2
类中拥有冗余锁(或者将它们与Class1
进行间接耦合而删除) )。如果Class1
用其他方法扩展,甚至更糟的是,有人决定通过另一个锁定对象向Class1
添加额外的线程安全(在最坏的情况下,我们可能会出现死锁)。因此,每次我们在Class1
中进行此类更改时,我们还必须检查Class2
代码,以确保没有任何问题,换句话说,由于{{1 }}的责任不应该属于它。 Class2
的使用情况。一般建议:
答案 1 :(得分:1)
如果要以线程安全的方式使用Class1
(或该事件的后代类),则应使用封装而不是继承,如Kevin Gosse所述。不应以这种方式使用继承,因为如果Class1
具有更多非虚拟的方法(甚至是公共方法),这些方法会更改对象的内部状态,则您将无法对其进行任何控制。您应该采用并封装一个继承Class1
的类,然后公开将被称为线程安全方法的方法。
即使您确实控制Class1
设计,每次添加或更改Class2
的方法时都要想到线程安全继承者(Class1
)也是一个糟糕的设计。