Ran into this, is there any reason why kotlin byte...
# announcements
s
Ran into this, is there any reason why kotlin bytecode ignores synchronization primitive for get()
Copy code
var data = false
    @Synchronized get
    @Synchronized set(value) { field = !value }

fun main() {
    println("Value $data")
}
The only way to get bytecode to call getData() is by having this redundant get (which is prompted as redundant getter in IDE)
Copy code
@Synchronized get() = field
n
can you share more? bytecode looks synchronized to me
Copy code
public final static synchronized getData()Z
   L0
    LINENUMBER 1 L0
    GETSTATIC SyncKt.data : Z
    IRETURN
   L1
    MAXSTACK = 1
    MAXLOCALS = 0
s
getData() is defined as synchronized but the call site doesn't invoke getData(), instead it uses data directly
n
Copy code
GETSTATIC SyncKt.data : Z
this? .....yeah, that seems to corroborate that
s
yup, if you decompile that,
Copy code
private static boolean data;

   public static final synchronized boolean getData() {
      return data;
   }

   public static final synchronized void setData(boolean value) {
      data = !value;
   }

   public static final void main() {
      String var0 = "Value " + data;
      System.out.println(var0);
   }
n
well, I've been told before that the decompiler is approximate, but in this case they do seem to be in agreement
(for example, the bytecode creates a StringBuilder)
which version of Kt is this?
s
1.4.0
n
repros for me on 1.3.72 also. sounds like a bug worth reporting.
s
Sound good
n
I think the YouTrack search might be having a bad time right now...some of my search queries are taking >30 seconds
s
yup likewise
n
oh well. good luck 😛 link back for us when you find something or report a new issue 😄
s
Sure
a
field = !value
? That sounds like a recipe for confusion.
n
I'm assuming it's just an example
s
@araqnid yeah foobar, just to get around lint warning
a
If you really just want to wrap synchronization around that field access, you could do this of course:
Copy code
private var privateData = false
    get() = synchronized(this) { field }
    set(value) { synchronized(this) { field = value } }
With some added fun if you want this for a top-level property (maybe lock some class object similar to what
static synchronized
in Java does) Or even just create a delegate for applying synchronization a la
private var privateData by synchronizeOn(this) { false }
But yes, the current situation where the
@Synchronized
annotation is ignored here seems wrong
s
yeah, Delegates works better. This was just to confirm and report the issue.
👍🏻 1
k
What is the
@Syncronised
supposed to do here
Standard getters get converted into standard field accessed by the JVM. Idk if this prevents that but I don't see why reading has to be synchronised?
n
in case something is setting it at the same time
k
I don't think this will do anything about that? I thought this just prevents two threads from reading the field at the same time, which should be just fine.
n
if you synchronized on the getters and setters in Java it would though
k
Oh, my bad, I thought synchronised was on a method basis instead of working for the full object. But shouldn't you make the variable volatile then too?
n
@Synchronized adds "synchronization barriers" that cause caches to be read/flushed upon entering/exiting them, IIRC, so adding volatile would be redundant.
though tbh this isn't my strong suit and I'm not looking in the right places for documentation apparently