java支持多个线程访问一个对象或者对象的成员变量,由于每个线程可以拥有这个变量的拷贝,所以在程序执行的过程中,一个线程看到的变量并不一定是最新的
volatile:用来修饰成员变量,告知程序对成员变量的访问均需要从共享内存中获取,而对它 的改变必须同步刷新回共享内存,保证所有线程对变量访问的可见性
synchronized:用于修饰方法或者同步块的形式使用,主要确保多个线程在同一时刻,只能有一个线程进入方法或者同步块,保证线程对变量访问的可见性和排他性
public class Sy {
public static void main(String[] args) {
synchronized (Sy.class) {
}
//静态同步方法,对synchronized class对象进行加锁
m();
}
public static synchronized void m() {
}
}
使用javap工具查看生成的class分析synchronized关键字的具体细节
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=1
0: ldc #2 // class com/demo/demo4/Sy
2: dup
3: astore_1
4: monitorenter
5: aload_1
6: monitorexit
7: goto 15
10: astore_2
11: aload_1
12: monitorexit
13: aload_2
14: athrow
15: invokestatic #3 // Method m:()V
18: return
Exception table:
from to target type
5 7 10 any
10 13 10 any
public static synchronized void m();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
Code:
stack=0, locals=0, args_size=0
0: return
LineNumberTable:
line 15: 0
在上面的class信息中,对于同步块实现使用了monitorenter和monitorexit指令而同步方法是依靠方法上面的修饰符ACC_SYNCHRONIZED来完成的,本质都是对一个对象的监视器进行获取,这个获取的过程是排他的,也就是同一时刻只能有一个线程获取到由synchronized所保护的对象监视器
每一个对象都有自己的监视器,这个对象由同步块或者同步方法调用时,执行方法的的线程就必须先获取对象的监视器才能进入同步块或者是同步方法,没有获取到监视器的线程将会被阻塞在入口处,进入BLOCKED状态

本文深入探讨Java中synchronized关键字的工作原理,包括其如何通过monitorenter和monitorexit指令实现同步块的互斥访问,以及ACC_SYNCHRONIZED标志如何用于同步方法。解释了对象监视器的概念及其实现线程间的可见性和排他性。
575

被折叠的 条评论
为什么被折叠?



