java - 在单例工厂中同步和锁定

标签 java multithreading locking singleton synchronized

我有一个单例工厂(编辑:重命名为“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 构造函数可见。此外,拥有一个加载器类可能会变成垃圾场,它鼓励按层而不是按功能进行组织。

您可以考虑使用 Initialization-on-Demand holder idiom :

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;
    }
}

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

关于java - 在单例工厂中同步和锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35707141/

相关文章:

java - 消息字符集

java - Junit4 和 TestNG 在与 Maven 的一个项目中

java - On Event Dispatch Thread---想摆脱它

java - 增加和删除 ConcurrentHashMap 的元素

c++ - C++ 中独立于操作系统的线程?

java - 使用java FileChannel FileLock来防止文件写入但允许读取

java - 将int文字传递给在java中采用整数的方法

java - 具有多个文件夹的 Sftp OutboundAdapter

java - com.ibm.db2.jcc.am.SqlTransactionRollbackException : DB2 SQL Error: SQLCODE=-911, SQLSTATE=40001,SQLERRMC=68,DRIVER=3.65.110

objective-c - 如何在Objective-C中的原子属性的ivar上创建手动锁定?