在科特林中使用原子布尔值是个好主意吗?
Is it good idea to use atomic boolean in kotlin?
嘿,我正在学习 kotlin 中的原子。我想知道在我的场景中使用原子布尔值是个好主意吗?有人可以建议,如何以原子方式做。
场景一不适合第一次调用
var isFirstTime = true
fun notForFirstTime(){
if(!isFirstTime){
jobDone()
}
isFirstTime = false
}
场景二 仅限第一次
var isFirstTime = true
fun onlyForFirstTime(){
if(isFirstTime){
jobDone()
}
isFirstTime = false
}
我可以用原子方式来做吗?这也是个好主意吗?
这取决于您要实现的目标。
对于场景 2,大多数时候您需要的是计算一次并在以后重复使用的值。对于此 use-case,您可以像这样使用 lazy
委托:
class MyClass {
// will be computed the first time it's accessed, and then reused
val value by lazy { computeExpensiveValue() }
}
fun computeExpensiveValue(): Int {
// some complex stuff
return 42
}
我从未遇到过场景 1,但在 lazy
不够用的情况下,您确实可以将原子布尔值用于 CAS 方法或锁。例如检查 kotlinx.atomicfu.
如果您使用的是 Kotlin 协程,您可能需要检查其他同步原语,例如 Mutex and Semaphore。但总的来说,最好让协程通过通道进行通信而不是共享可变状态。
不太清楚你问的是什么。但是假设你想确保一些代码只在第一次执行(或不执行)并且函数可以并发调用(因为你要求“原子”)那么答案是:不,不。您的两个代码示例都不是 thread-safe,并且可能会导致比第一个调用更多的调用以特殊方式处理。
这不是因为布尔值不是原子的,而是因为您的代码不是原子的。两个或多个并发线程可以同时检查 isFirstTime
,然后其他线程会将其翻转为 false
。
您可以通过多种方式解决这个问题,例如使用互斥锁,但最简单和性能最好的可能是使用 compare and swap operations 之一。例如:
val isFirstTime = AtomicBoolean(true)
fun notForFirstTime(){
if (!isFirstTime.getAndSet(false)) {
jobDone()
}
}
fun onlyForFirstTime(){
if (isFirstTime.getAndSet(false)) {
jobDone()
}
}
嘿,我正在学习 kotlin 中的原子。我想知道在我的场景中使用原子布尔值是个好主意吗?有人可以建议,如何以原子方式做。
场景一不适合第一次调用
var isFirstTime = true
fun notForFirstTime(){
if(!isFirstTime){
jobDone()
}
isFirstTime = false
}
场景二 仅限第一次
var isFirstTime = true
fun onlyForFirstTime(){
if(isFirstTime){
jobDone()
}
isFirstTime = false
}
我可以用原子方式来做吗?这也是个好主意吗?
这取决于您要实现的目标。
对于场景 2,大多数时候您需要的是计算一次并在以后重复使用的值。对于此 use-case,您可以像这样使用 lazy
委托:
class MyClass {
// will be computed the first time it's accessed, and then reused
val value by lazy { computeExpensiveValue() }
}
fun computeExpensiveValue(): Int {
// some complex stuff
return 42
}
我从未遇到过场景 1,但在 lazy
不够用的情况下,您确实可以将原子布尔值用于 CAS 方法或锁。例如检查 kotlinx.atomicfu.
如果您使用的是 Kotlin 协程,您可能需要检查其他同步原语,例如 Mutex and Semaphore。但总的来说,最好让协程通过通道进行通信而不是共享可变状态。
不太清楚你问的是什么。但是假设你想确保一些代码只在第一次执行(或不执行)并且函数可以并发调用(因为你要求“原子”)那么答案是:不,不。您的两个代码示例都不是 thread-safe,并且可能会导致比第一个调用更多的调用以特殊方式处理。
这不是因为布尔值不是原子的,而是因为您的代码不是原子的。两个或多个并发线程可以同时检查 isFirstTime
,然后其他线程会将其翻转为 false
。
您可以通过多种方式解决这个问题,例如使用互斥锁,但最简单和性能最好的可能是使用 compare and swap operations 之一。例如:
val isFirstTime = AtomicBoolean(true)
fun notForFirstTime(){
if (!isFirstTime.getAndSet(false)) {
jobDone()
}
}
fun onlyForFirstTime(){
if (isFirstTime.getAndSet(false)) {
jobDone()
}
}