Difference between Lock.withLock and synchronized in Kotlin

It's worth adding to @s1m0nw1's answer explicitly that they can have different semantics, depending on what lock you use. Quoting the Lock documentation:

A Lock class can also provide behavior and semantics that is quite different from that of the implicit monitor lock, such as guaranteed ordering, non-reentrant usage, or deadlock detection. If an implementation provides such specialized semantics then the implementation must document those semantics.

Note that Lock instances are just normal objects and can themselves be used as the target in a synchronized statement. Acquiring the monitor lock of a Lock instance has no specified relationship with invoking any of the lock() methods of that instance. It is recommended that to avoid confusion you never use Lock instances in this way, except within their own implementation.


The extension withLock works on Lock instances like ReentrantLock, whereas synchronized may be used with any object.

val lock = ReentrantLock()
fun syncWithLockTest(): Int = lock.withLock { 123 }

val anyLock = Any()
fun syncWithArbitraryObjTest(): Int = synchronized(anyLock) { 123 }

Note that synchronized is a function in Kotlin which returns a value. This makes it more powerful than Java's synchronized keyword. Technically it doesn’t make a difference on which object you lock, as long as you use the same object for all relevant code blocks that need be synchronized with each other and don't expose it publicly.

Tags:

Kotlin