1、 synchronized 作用
原子性:synchronized保证语句块内操作是原子的
可见性:synchronized保证可见性(通过"在执行unlock之前,必须先把此变量同步回主内存”实现)
有序性:synchronized保证有序性(通过"一个变量在同一时刻只允许一条线程对其进行lock 操作”)
2、synchronized 的使用
3、
修饰实例方法,对当前实例对象加锁
修饰静态方法,多当前类的Class对象加锁
修饰代码块,对synchronized括号内的对象加锁
3、 synchronized 实现原理
jvm基于进入和退出Monitor对象来实现方法同步和代码块同步
方法级的同步是隐式,即无需通过字节码指令来控制的,它实现在方法调用和返回操作之中。
JVM可以从方法常量池中的方法表结构(method_info Structure)中的ACC_SYNCHRONIZED访
问标志区分一个方法是否同步方法。当方法调用时,调用指令将会检查方法的
ACC_SYNCHRONIZED访问标志是否被设置,如果设置了,执行线程将先持有monitor (虚拟机 规范中用的是管程一词),然后再执行方法,最后再方法完成(无论是正常完成还是非正常完 成)时释放monitor。
代码块的同步是利用monitorenter和monitorexit这两个字节码指令。它们分别位于同步代 码块的开始和结束位置。当jvm执行到monitorenter指令时,当前线程试图获取monitor对 象的所有权,如果未加锁或者已经被当前线程所持有,就把锁的计数器+1;当执行monitorexit 指令时,锁计数器-1;当锁计数器为0时,该锁就被释放了。如果获取monitor对象失败,该 线程则会进入阻塞状态,直到其他线程释放锁。
这里要注意:
1、 synchronized是可重入的,所以不会自己把,自己锁死
2、 synchronized锁一旦被一个线程持有,其他试图获取该锁的线程将被阻塞。
关于ACC_SYNCHRONIZED、monitorenter、monitorexit指令,可以看一下下面的反编译代码:
public class SynchronizedDemo {
public synchronized void f() { //这个是同步方法
System.out.println("Hello world");
}
public void g() {
synchronized (this) { //这个是同步代码块
System.out.println("Hello world");
}
}
public static void main(String[] args) {
}
}

Was this helpful?

0 / 0

发表回复 0

Your email address will not be published.