22

So I'm trying to get a handle on how Kotlin handles synchronization of properties. If I have this class:

class Foo {
    var a = 0
    var b = 0
}

and I want to make sure that a & b have all access synchronized. How would I do it? I've tried using the annotation:

class Foo {
    @Synchronized
    var a = 0
    @Synchronized
    var b = 0
}

but Kotlin gives me a compiler error:

This annotation is not applicable to target 'member property with backing field'

I'm just trying to get a better handle on thread safety in Kotlin. It's something that I've always been OCD about in Java, and I'm trying to figure out how to properly handle it in Kotlin.

stkent
  • 19,772
  • 14
  • 85
  • 111
craigmiller160
  • 5,751
  • 9
  • 41
  • 75

2 Answers2

42

You can't synchronize on a property but you can synchronize on the accessor methods. Use the following syntax:

class Foo {
    var a = 0
        @Synchronized get
        @Synchronized set   

    //or

    @get:Synchronized @set:Synchronized
    var b = 0
}
Kirill Rakhman
  • 42,195
  • 18
  • 124
  • 148
6

Followed by the @Kirill Rakhman's answer, use of Delegates could be more performant if there is tons of contention to the same object since it locks on the delegate rather than the whole object.

class Foo {
    var a by Synchronize(0)
    var b by Synchronize(0)
}

class Synchronize<T>(defaultValue: T): ReadWriteProperty<Any, T> {
    private var backingField = defaultValue

    override fun getValue(thisRef: Any, property: KProperty<*>): T {
        return synchronized(this) {
            backingField
        }
    }

    override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
        synchronized(this) {
            backingField = value
        }
    }
}

References: Kotlin Delegated Properties Reddit Discussion

Rishav Chudal
  • 171
  • 1
  • 8