【问题标题】:Should the singleton methods be synchronized?单例方法应该同步吗?
【发布时间】:2016-07-09 02:26:23
【问题描述】:

我的网络应用程序(这里没有 Spring-MVC,只有核心 IOC)使用了很多原型 bean,其中大多数都使用单例 dao-bean。单例 dao-bean 方法是否应该同步,因为许多不同的原型 bean(来自不同的请求)可能在同一时刻使用相同的方法 id dao?

比如dao方法

public void setLetterNotNew(int letterId) {

    final String sql = "UPDATE income SET isnew=? WHERE id=?";

    try( Connection con = HikariFactory.getConnection(); PreparedStatement ps = con.prepareStatement(sql); ) {

        ps.setInt(1, 0);
        ps.setInt(2, letterId);

        int i = ps.executeUpdate();
        if(i==0) throw new SQLException("setLetterNotNew");

    } catch (SQLException e) {
        log.error(e);
    }
}

【问题讨论】:

  • 取决于您如何更新数据库。许多框架已经同步,因此您不必做任何额外的工作。检查您的文档。
  • @markspace 这里没有任何框架,除了 spring-ioc。这是一个基于 servlet 的网络应用程序。数据库正在通过标准 jdbc 更新。
  • 是的,您应该使单例的方法同步或至少在同步块之间同步到数据库的部分。还要检查你计划如何构建和获取单例,这样你就不会得到两个实例
  • 如果多个线程访问共享的可变状态,则需要同步。我们不知道您的“在此处更新数据库”的作用。如果它从数据源获得连接,执行它的 jow 并关闭连接,则不需要同步。由于您已经使用 Spring,因此您绝对应该使用它的声明式事务支持及其 JDBC 相关类(JdbcTemplate 等)。也许您已经这样做了,但是由于您没有发布任何代码...
  • @Rumal 创建单例是 Spring 的任务,所以我认为我们不必担心。

标签: java spring multithreading singleton spring-ioc


【解决方案1】:

视情况而定。

正如您在评论中所写,您使用 jdbc。对 JDBC API are synchronized 和做 auto-commit by default 的所有操作。因此,如果您共享 JDBC 连接,但您的方法不需要事务(例如,它不会对之前选择的几行数据进行更新),则不需要同步。

但是,如果您需要事务,则必须同步此方法或为每个线程提供其自己的 JDBC 连接,如 each connection is also a transaction。为此,您可以每次在方法中打开新连接或让Spring handle that problem

【讨论】:

  • 如何定义该方法是否需要事务?我更新了问题。我从池中获取连接(静态方法 HikariFactory.getConnection())并且连接自动关闭。我也知道 Jdbc 在数据库级别处理多线程。所以有问题的方法不包含任何状态。在这种情况下,多线程怎么会做错事呢?其实我认为最好的想法是使用原型为道豆,那么就不用担心多头了。
  • 如果该方法不包含任何状态,那么您可以安全地使用它,而无需将 dao 更改为原型 bean 或同步它。如果您的声明是单次更新,则不需要任何事务。事务用于确保同时使用的多个查询处理数据库中的相同数据。在您的情况下,只有一个语句,所以没有问题。
猜你喜欢
  • 2019-01-14
  • 2012-12-16
  • 2011-03-26
  • 1970-01-01
  • 2020-03-17
  • 1970-01-01
  • 1970-01-01
  • 2017-01-14
相关资源
最近更新 更多