我有一个应用程序,我想确保一个方法最多同时调用一次,比如在更新数据库中的用户余额时。在Scala/Java中使用AtomicBoolean进行数据库锁定安全吗?
我想到的是使用下面的锁体:(显示Scala代码的下方,而应该是与Java Lambda表达式类似):
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)
}
}
这是安全使用时usingAtoimcDB
可以同时叫什么名字?
编辑:下面的校正码,如指向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")
}
}
编辑2:
使用SPINLOOP。这也可以吗?
def usingAtoimcDB[T](f: => T):T = {
while (!dbLocked.compareAndSet(false, true)) {Thread.sleep(1)}
try f
finally dbLocked.set(false)
}
编辑3:根据下面的答案和评论,我也在考虑使用队列。
在Java中使用它是否安全?如果是,那么它将从Scala安全。 –
@SarveshKumarSingh添加了Java标记,所以Java人可以回答这个问题。 – Jus12
您上面发布的代码不是线程安全的;两个线程可以通过'if(dbLocked.get)'调用并设置原子布尔值。您必须使用'compareAndSet'方法使其成为原子。像'java.util.concurrent.locks.ReentrantReadWriteLock'这样的类比AtomicBoolean更合适。 – Jesper