Checkstyle将此代码报告为"双重检查锁定习语已损坏",但我认为我的代码实际上并未受到双重检查锁定问题的影响.
如果不存在具有该id的行,则该代码应该在数据库中创建一行.它在多线程环境中运行,我想避免主键存在的SQL异常.
伪代码:
private void createRow(int id) { Row row = dao().fetch(id); if (row == null) { synchronized (TestClass.class) { row = dao().fetch(id); if (row == null) { dao().create(id); } } } }
我可以同意它看起来像双重检查锁定,但我没有使用静态变量,fetch()和create()中的代码可能太复杂,无法内联并使其无序.
我错了还是格式?:)
我认为在这种情况下,checkstyle是正确的.在您提供的代码中,考虑如果两个线程都row == null
在synchronized块的入口处会发生什么.线程A将进入块,并插入新行.然后在线程A退出块后,线程B将进入块(因为它不知道刚刚发生了什么),并尝试再次插入相同的新行.
我看到你刚刚更改了代码,并在那里添加了一个非常重要的缺失行.在新代码中,您可能能够避免这种情况,因为两个线程不会依赖于对共享(静态)变量的更改.但是你可能会更好地看看你的DBMS是否支持如下的语句INSERT OR UPDATE
.
将此功能委派给DBMS的另一个好理由是,您需要部署多个应用程序服务器.由于synchronized
块不能跨机器工作,因此无论如何都必须在其他情况下执行其他操作.