Reputation: 943
Is it known that you cannot synchronize an inlined function in Kotlin? I cannot find any documentation on this.
Imagine you have a class with a synchronized method;
/**
* Allows modifying the value in a synchronized way so that the get() and set() are atomic.
*
* Note: anything synchronized cannot be `inline`.
*/
@Synchronized fun safeSet(calculateNewValue: (T) -> T) {
set(calculateNewValue(get()))
}
When this function is inlined
this test fails, when it is not inlined
it passes.
@Test
fun `safeSet - is synchronized`() {
val insideSet = AtomicInteger()
val threadsRun = CountDownLatch(2)
val t1 = Thread({
threadsRun.countDown()
sut.safeSet { currentValue: Int ->
insideSet.incrementAndGet()
try {
Thread.sleep(100000)
} catch (interrupted: InterruptedException) {
BoseLog.debug(interrupted)
}
currentValue + 1
}
})
t1.start()
val t2 = Thread({
threadsRun.countDown()
sut.safeSet { currentValue: Int ->
insideSet.incrementAndGet()
try {
Thread.sleep(100000)
} catch (interrupted: InterruptedException) {
BoseLog.debug(interrupted)
}
currentValue + 2
}
})
t2.start()
threadsRun.await()
Thread.sleep(100)
assertEquals(1, insideSet.get())
t1.interrupt()
t2.interrupt()
Thread.sleep(100)
assertEquals(2, insideSet.get())
}
Upvotes: 2
Views: 481
Reputation: 97328
The @Synchronized
annotation tells the compiler to generate the ACC_SYNCHRONIZED
flag on the method. Inline functions are not compiled to methods, so the annotation is indeed ignored.
There is an open issue in Kotlin for handling this situation better.
Upvotes: 5