有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用“setter”/实例变量会导致单例DAO的竞争条件吗?

假设下面的类是单例

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) 个答案

  1. # 1 楼答案

    如果多个线程正在调用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配置的一部分来完成,Spring配置是单线程完成的

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

  2. # 2 楼答案

    如果setItemType方法只在初始化时使用(例如,通过Spring配置),并且如果Spring强制执行适当的内存屏障,以确保在使用前所有线程中都可以看到该值,那么它可能没问题,但有点异味。这就是构造器注入更简洁的地方,因为您可以将其设置为final变量,这显然不是什么大问题

    如果在初始化之后使用setItemType方法,那么这肯定是一个问题。您可能需要到处都有多个实例(例如,每个类需要一个DAO引用),或者每个项类型可能需要一个实例:声明几个单独的bean,然后根据需要的类型为每个需要DAO的类提供一个“正确”实例的引用