I’m working on a Kotlin application where I need to manage BigDecimal values atomically to ensure thread safety. Given Kotlin’s interoperability with Java, I am considering using Java’s AtomicReference, but I am not entirely sure how to correctly implement operations like addition or compare-and-set on BigDecimal.
Here is my current implementation:
import java.math.BigDecimal
import java.util.concurrent.atomic.AtomicReference
data class Account(
var totalBalance: AtomicReference<BigDecimal>,
var availableBalance: AtomicReference<BigDecimal>,
var unavailableBalance: AtomicReference<BigDecimal> = AtomicReference(BigDecimal.ZERO)
) {
@Synchronized
fun withdraw(amount: BigDecimal) {
availableBalance.updateAndGet { it - amount }
}
@Synchronized
fun deposit(amount: BigDecimal) {
availableBalance.updateAndGet { it + amount }
}
@Synchronized
fun transfer(amount: BigDecimal) {
availableBalance.updateAndGet { it - amount }
unavailableBalance.updateAndGet { it + amount }
}
}
My Questions:
1.Does Kotlin’s AtomicReference behave identically to Java’s AtomicReference in a multi-threaded environment?
2.Are there any major differences between the two implementations that I should be aware of?
3.When might it be more appropriate to use Kotlin’s version over Java’s, especially in the context of a multi-threaded environment?
Project Details:
-
Kotlin version: 1.9.20
-
build.gradle.kts:
plugins {
id("org.springframework.boot") version "3.2.0" apply false
id("io.spring.dependency-management") version "1.1.4" apply false
kotlin("jvm") version "1.9.20" apply false
kotlin("plugin.spring") version "1.9.20" apply false
}
I tried running the transfer function in a multi-threaded environment, where two threads execute the function simultaneously
I expected the balances to be updated correctly, maintaining the consistency of the account balances. However, I noticed that the values were not updated as expected. The updates were not atomic, leading to incorrect balance values (maybe) due to race conditions.