How do I initialize properties of a class under a common lock?


#1

I fail to see how to properly initialize class properties. I need something like this:

class Foo {
  private var foo: Int
  private var bar: Boolean

  init {
    synchronized(this) {
      foo = 1
      bar = true
    }
  }
}

However, the compiler wants foo and bar initialized at declaration, even though they are initialized in a constructor.


#2

Wow, it compiles with 1.3. I guess that’s the answer.


#3

If you want to know why this works now you should take a look at contracts. It’s a new feature in 1.3 (the api for it is still experimental, but the functionality is stable).


#4

One point though. In most cases synchronization is not needed in a constructor. A constructor is invoked from a single thread and any reference is only available externally after the constructor finished (Unless you leak your this pointer in the constructor, something the compiler tries to warn against). Be aware though that no memory fence is created after construction so when passing an object to another thread it could see the uninitialised state of the object (as the JVM/CPU can and will reorder instructions). In your case the way to do this in all cases would be an empty synchronized block where the initialisation is done normally.

This is covered in section 17.5 of the jls. It guarantees that final fields do not need an explicit barrier. The explanation in exable 17.5-1 explicitly makes clear that this is not the case for non-final fields (vars).


#5

Yes, that’s why I wanted to initialize the fields inside synchronized.
As for the empty synchronized section — I don’t know for sure if the JVM is prohibited from optimizing it away. On the surface of it, it shouldn’t, but I’d (and the reviewer/maintainer) would need to look it up. Another problem is that the intent gets obscured in this way.

All in all, I’m glad that the contracts now allow me to express it in a clear way.