Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jvm differences between synchronized and non-synchronized methods

Tags:

java

jvm

I have the following class:

public class SeqGenerator {

    int last = 0;
    volatile int lastVolatile = 0;

    public int getNext() {
        return last++;
    }

    public synchronized int getNextSync() {
        return last++;
    }

    public int getNextVolatile() {
        return lastVolatile++;
    }

    public void caller() {
        int i1 = getNext();
        int i2 = getNextSync();
        int i3 = getNextVolatile();
    }

}

When I look at the disassembled code I don't see the difference between the representation of three methods getNext(), getNextSync() and getNextVolatile() .

public int getNext();
  Code:
   0:   aload_0
   1:   dup
   2:   getfield    #2; //Field last:I
   5:   dup_x1
   6:   iconst_1
   7:   iadd
   8:   putfield    #2; //Field last:I
   11:  ireturn

public synchronized int getNextSync();
  Code:
   0:   aload_0
   1:   dup
   2:   getfield    #2; //Field last:I
   5:   dup_x1
   6:   iconst_1
   7:   iadd
   8:   putfield    #2; //Field last:I
   11:  ireturn

public int getNextVolatile();
  Code:
   0:   aload_0
   1:   dup
   2:   getfield    #3; //Field lastVolatile:I
   5:   dup_x1
   6:   iconst_1
   7:   iadd
   8:   putfield    #3; //Field lastVolatile:I
   11:  ireturn

public void caller();
  Code:
   0:   aload_0
   1:   invokevirtual   #4; //Method getNext:()I
   4:   istore_1
   5:   aload_0
   6:   invokevirtual   #5; //Method getNextSync:()I
   9:   istore_2
   10:  aload_0
   11:  invokevirtual   #6; //Method getNextVolatile:()I
   14:  istore_3
   15:  return

How the JMV can distinguish between these methods?

The generated code is the same of these methods and also of their callers. How the JVM performs the synchronization?

like image 742
Oleg Pavliv Avatar asked Oct 05 '11 06:10

Oleg Pavliv


2 Answers

The synchronized keyword applied to a method just sets the ACC_SYNCHRONIZED flag on that method definition, as defined in the JVM specification § 4.6 Methods. It won't be visible in the actual bytecode of the method.

The JLS § 8.4.3.6 synchronized Methods discusses the similarity of defining a synchronized method and declaring a synchronized block that spans the whole method body (and using the same object to synchronize on): the effect is exactly the same, but they are represented differently in the .class file.

A similar effect happens with volatile fields: It simply sets the ACC_VOLATILE flag on the field (JVM § 4.5 Fields). The code that accesses the field uses the same bytecode, but acts slightly different.

Also please note that using only a volatile field here is not threadsafe, because x++ on a volatile field x is not atomic!

like image 92
Joachim Sauer Avatar answered Nov 13 '22 08:11

Joachim Sauer


The difference between the first two is right here:

public int getNext();
   bytecodes follow...

public synchronized int getNextSync();
   bytecodes follow...

As to the last one, volatile is a property of the variable, not of the method or the JVM bytecodes that access that variable. If you look at the top of the javap output, you'll see the following:

int last;

volatile int lastVolatile;

If/when the bytecodes are compiled into machine code by the JIT compiler, I am sure the resulting machine code will differ for the last method.

like image 45
NPE Avatar answered Nov 13 '22 09:11

NPE