【问题标题】:synchronized on local variable, better than synchronized methods?在局部变量上同步,比同步方法更好?
【发布时间】:2013-11-01 17:00:55
【问题描述】:

我为数据库查询编写了一个包装器,需要从不同的线程访问它。因此,我的应用程序只创建了该帮助程序类的一个实例,并通过 getter 将其返回。

DbConnection dbc = app.getDatabaseConnection();
synchronized (dbc) {
  dbc.doSomething();
}

这段代码安全吗?如here 所述,尽管在局部变量上同步,但它应该可以工作。只要保证对象实例相同,这是否正确?

让所有受影响的 DbConnection 实例方法同步是否更好?

【问题讨论】:

  • 如果可能的话,你应该让dbc 成为private,更重要的是final。

标签: java multithreading thread-safety synchronized local-variables


【解决方案1】:

这不是好的设计。

不是通过在必要时同步其方法/块来使您的 DBConnection 类本质上是线程安全的,而是强制该类的所有客户端在每次需要时显式地同步。因此,您不是将线程安全性封装在一个明确的类中,而是将这个责任分配给该类的所有客户端,这使得整个事情变得非常脆弱,并且潜在的错误非常难以发现。

也就是说,使用来自多个线程的单个数据库连接本身就是一个坏主意。

【讨论】:

  • 是锁数据库连接,只能有一个连接。我知道同步在这里有缺点,但由于应用程序传输少量数据,这应该不是问题。
  • 因此,假设底层数据库连接是线程安全的(这已经是一个疯狂的猜测),假设线程 A 启动了一个事务,然后不相关的线程 B 也尝试启动一个事务。你打算如何进行这项工作?为什么不使用连接池,如果真的需要,甚至减少到 1 个连接。这至少可以确保两个线程不会同时使用同一个连接。
  • 数据库的流量确实很少。如果所有事务都由提供同步方法的适配器(DbConnection)执行,它不应该工作吗?如果这是一个愚蠢的问题,我很抱歉,但我过去没有在数据库和线程安全方面做太多工作。 (我同意,类名具有误导性。将在一些提交中更改它。)
  • 如果整个事务在单个同步方法中完成,它将起作用。如果只是同步getDatabaseConnection(),那么两个线程将无法同时获得连接。但是一旦他们都成功(按顺序)获得它,他们仍然可以同时使用它。
  • 如果我使用 synchronized void writeSomething 和 synchronized ... readSomething 应该可以工作(假设两者都是 DbConnection 的实例方法),不是吗?
【解决方案2】:

如果您的 DbConnection 的所有实例方法都需要同步,则使所有方法同步。不要看你写的代码量,只看正确性。如果您同步每个方法,您就没有机会回到几年后调用 getDatabaseConnection 然后忘记同步。

【讨论】:

    猜你喜欢
    • 2014-12-16
    • 2014-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-04
    • 1970-01-01
    相关资源
    最近更新 更多