在单例工厂中同步和锁定



我有一个单例工厂(编辑:重命名为"loader"以避免与工厂模式混淆),它创建对象(在我的示例中为DAO)或返回它们(如果已经创建):

public class DAOLoader {
    private static final DAOLoader INSTANCE = new DAOLoader();
    private UserDAO userDAO;
    private MessageDAO messageDAO;
    private final Object lockUserDAO = new Object();
    private final Object lockMessageDAO = new Object();
    private DAOLoader() {}
    public static DAOLoader getInstance() {
        return INSTANCE;
    }
    public UserDAO getUserDAO() {
        if (userDAO == null) {
            synchronized(lockUserDAO) {
                if (userDAO == null) userDAO = new UserDAO();
            }
        }
        return userDAO;
    }
    public MessageDAO getMessageDAO() {
        if (messageDAO == null) {
            synchronized(lockMessageDAO) {
                if (messageDAO == null) messageDAO = new MessageDAO();
            }
        }
        return messageDAO;
    }
}

首先,你们觉得这段代码有什么问题吗?
在此示例中,每个方法是否需要不同的锁,还是我应该只使用 1 个全局锁?使用唯一的全局锁会发生死锁吗?如果没有,唯一的缺点是,如果某个线程使用锁来创建 DAO,而另一个线程想要创建另一个 DAO,它将不得不等待锁被释放?

谢谢。

你的例子似乎有点混乱,因为你阻止了 DaoLoader 的构造函数可见,但你没有阻止 Dao 构造函数可见。此外,拥有加载器类可以变成事物的垃圾场,它鼓励按层而不是按功能组织。

您可以考虑使用按需初始化持有者习惯用法:

public class UserDao {
    private UserDao() {}
    String findById(Long id) {
        return "foo";
    }
    private static class LazyUserDaoHolder {
        static final UserDao USER_DAO_INSTANCE = new UserDao();
    }
    public static UserDao getInstance() {
        return LazyUserDaoHolder.USER_DAO_INSTANCE;
    }
}

在调用访问它的方法之前,不会初始化持有者静态类,因为它是在第一次访问时初始化的(并且类初始化是串行的),因此不需要同步。

最新更新