在Scala/Java中使用AtomicBoolean进行数据库锁定是否安全?

Jus*_*s12 2 java multithreading scala java.util.concurrent

我有一个应用程序,我想确保一个方法最多同时调用一次,比如在数据库中更新用户余额时.

我正在考虑使用以下锁定机制:(显示下面的Scala代码,但应该与Java Lambdas类似):

object Foo{
    val dbLocked = new java.util.concurrent.atomic.AtomicBoolean(false)

    def usingAtoimcDB[T](f: => T):T = {
        if (dbLocked.get) throw new Exception("db is locked")
        dbLocked.set(true)
        try f
        finally dbLocked.set(false)    
    }
}
Run Code Online (Sandbox Code Playgroud)

usingAtoimcDB可以同时调用时使用是否安全?

编辑:下面更正的代码,如下面的答案所示:

def usingAtoimcDB[T](f: => T):T = {
  if(dbLocked.compareAndSet(false, true)) {
   //db is now locked
   try f
   finally dbLocked.set(false)
  } else {
   //db is already locked
   throw new Exception("db is locked")
  }
}
Run Code Online (Sandbox Code Playgroud)

编辑2:

使用spinloop.这也行吗?

def usingAtoimcDB[T](f: => T):T = {
  while (!dbLocked.compareAndSet(false, true)) {Thread.sleep(1)}
  try f
  finally dbLocked.set(false)
} 
Run Code Online (Sandbox Code Playgroud)

编辑3:根据下面的答案和评论,我也在考虑使用队列.

Joo*_*gen 6

不宜.您正在请求在同一服务器上的同一应用程序实例中运行的相同pieco代码是执行该事务的单点.也没有规定让这个代码脱颖而出.当您退休时,有人可能会启动第二个应用程序实例或其他任何内容.

而数据库提交/回滚是一个非常简单和可靠的机制.

如果你不能编写集成(单元)测试以确保这一点,那么就不要这样做.

如果你这样做:

  • 撤消对普通数据库用户的表修改的权限
  • 添加具有足够权限的新数据库用户

并且仍然:不要这样做.