可以使用'setter'/ instance变量导致单例DAO的竞争条件?

时间:2012-08-22 21:00:24

标签: java multithreading spring singleton race-condition

假设以下类是单身

public class myDAO {
    //determines the tableName and Id column names to based on itemType
    private String itemType;
    public void setItemType(String itemType) {...} 

    //Following methods use itemType to customize their queries
    public boolean findObj(int id){...} 
    public boolean deleteObj(int id){...}
    public boolean updateObj(Obj obj){...}
    //etc...
}

最近使用setter对代码进行了重构,从而为DAO提供了一些状态。我在Spring的配置文件中看到它被配置为singleton-scope。我有一种奇怪的感觉,这可能导致潜在的竞争条件。这是对的吗?

我真的不确定这是否确实如此,但如果确实如此,恕我直言就是噩梦般的情况。我知道这可能不是最好的设计,但我只是想知道当并发线程查询不同的itemTypes时是否会导致竞争条件。我在考虑将范围更改为prototype,但我不确定在这种情况下是否确实需要。

2 个答案:

答案 0 :(得分:2)

如果多个线程正在调用setItemType(...)然后调用findObj(...)并且期望找到具有id 的项目类型的对象然后是,那么你的奇怪感觉这是正确的,这是一种潜在的竞争条件,不适用于多线程应用程序。

您应该将itemType传递给您的每个方法:

public boolean findObj(String itemType, int id){...} 
public boolean deleteObj(String itemType, int id){...}
public boolean updateObj(String itemType, Obj obj){...}

如果在Spring构造DAO之后只设置了一次itemType,那么这是可以的,但应该作为Spring配置的一部分完成,这是单线程完成的。

如果你必须为所有或大多数方法添加一个itemType参数,那么在我看来你不再需要一个单例。相反,您应该考虑拥有DAO工厂或其他东西,并拥有多个DAO实例,每个实例都有自己的项类型。

答案 1 :(得分:2)

如果setItemType方法在初始化时使用(例如通过Spring配置),并且如果Spring强制执行适当的内存屏障以确保在使用前所有线程中都显示该值,那么它可能还可以 - 但有点气味。这是构造函数注入更整洁的地方,因为你可以将它变成final变量,这显然不是一个问题。

如果使用setItemType方法 post 初始化,那肯定是肯定一个问题。您将需要遍布整个地方的多个实例(例如,每个类需要一个DAO引用一个)或每个项类型可能有一个实例:声明几个单独的bean,然后为每个需要DAO的类提供对“对“一个取决于它需要哪种类型。