Jus12 Jus12 - 3 months ago 6
Java Question

Is it safe to use AtomicBoolean for database locking in Scala/Java?

I have an application where I want to ensure that a method is called at most once concurrently, say when updating user balance in a database.

I am thinking of using the following locking mechanism: (showing Scala code below, but should be similar with 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)
}
}


Is this safe to use when
usingAtoimcDB
may be called concurrently?

EDIT: The corrected code below, as pointed in this answer:

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")
}
}


EDIT 2:

Using a spinloop. Is this also ok?

def usingAtoimcDB[T](f: => T):T = {
while (!dbLocked.compareAndSet(false, true)) {}
try f
finally dbLocked.set(false)
}

Answer

Yes, it should work as espected. I would slightly modify your function using compareAndSet call.

compareAndSet method has the advantage to be an atomic operation - there are no race conditions and the value will be changed atomically.

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")
  }
}
Comments