同步并锁定单例工厂 [英] Synchronized and locks in singleton factory

查看:88
本文介绍了同步并锁定单例工厂的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a singleton factory (edit: renamed "loader" to avoid confusion with factory pattern) that creates objects (in my example DAOs) or returns them if already created:

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,则它必须等待锁被释放?

First, do you guys see anything wrong with this code?
In this example, is a different lock for each method required or should I just use 1 global lock? Would a deadlock happen with a unique global lock? If not, the only drawback would be that if the lock is used by some thread to create a DAO and another thread would like to create another DAO, it would have to wait for the lock to be released?

谢谢.

推荐答案

您的示例似乎有些困惑,因为您是在阻止DaoLoader的构造函数可见,但不是在阻止DaoLoader的构造函数可见.拥有装载程序类也可以成为事物的垃圾场,并且它鼓励按层而不是按功能进行组织.

Your example seems a bit confused because you're preventing the DaoLoader's constructor from being visible but you're not preventing the Dao constructors from being visible. Also having a loader class can turn into a dumping ground for things, and it encourages organizing by layer rather than by feature.

您可以考虑使用 Initialization-on-Demand持有人惯用语:

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静态类,因为它是在第一次访问时初始化的(并且类初始化是串行的),因此不需要同步.

The holder static class isn't initialized until the method accessing it is called, since it is initialized on first access (and class initialization is serial) no synchronization is required.

这篇关于同步并锁定单例工厂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆