jvm同步方法和非同步方法的区别
我有以下类:
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();
}
}
当我查看反汇编代码时,我看不到三个方法 getNext()
、getNextSync()
和 的表示之间的区别>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
JMV 如何区分这些方法?
这些方法及其调用者生成的代码是相同的。 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
应用于方法的
synchronized
关键字只是在该方法定义上设置ACC_SYNCHRONIZED
标志,如 JVM 规范第 4.6 节方法。它在方法的实际字节码中不可见。JLS § 8.4.3.6 同步方法 讨论定义
synchronized
方法和声明跨越整个方法体的synchronized
块(并使用相同的对象来同步)的相似性on):效果完全相同,但它们在.class
文件中的表示方式不同。易失性
字段也会发生类似的效果:它只是在字段上设置ACC_VOLATILE
标志(JVM § 4.5 字段)。访问该字段的代码使用相同的字节码,但行为略有不同。另请注意,这里仅使用易失性字段不是线程安全的,因为易失性字段
x
上的x++
是不是原子!The
synchronized
keyword applied to a method just sets theACC_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 asynchronized
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 theACC_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 fieldx
is not atomic!前两者之间的区别就在这里:
对于最后一个,
volatile
是变量的属性,而不是访问该变量的方法或 JVM 字节码的属性。如果您查看javap
输出的顶部,您将看到以下内容:如果/当 JIT 编译器将字节码编译为机器代码时,我确信生成的机器代码将有所不同最后一个方法。
The difference between the first two is right here:
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 thejavap
output, you'll see the following: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.