Jvm(50),指令集----同步指令

Posted qingruihappy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jvm(50),指令集----同步指令相关的知识,希望对你有一定的参考价值。

Java虚拟机可以支持方法级的同步和方法内部一段指令序列的同步,这两种同步结构都是使用管程(Monitor)来支持的。

方法级的同步是隐式的,即无须通过字节码指令来控制,它实现在方法调用和返回操作之中。虚拟机可以从方法常量池的方法表结构中的ACC_SYNCHRONIZED访问标志得知一个方法是否声明为同步方法。当方法调用时,调用指令将会检查方法的

ACC_SYNCHRONIZED访问标志是否被设置,如果设置了,执行线程就要求先成功持有管程,然后才能执行方法,最后当方法完成(无论是正常完成还是非正常完成)时释放管程。在方法执行期间,执行线程持有了管程,其他任何线程都无法再获取到同一个管程。如果一个同步方法执行期间抛出了异常,并且在方法内部无法处理此异常,那么这个同步方法所持有的管程将在异常抛到同步方法之外时自动释放。

同步一段指令集序列通常是由Java语言中的synchronized语句块来表示的,Java虚拟机的指令集中有monitorentermonitorexit两条指令来支持synchronized关键字的语义,正确实现synchronized关键字需要Javac编译器与Java虚拟机两者共同协作支持,譬如代码清单6-6中所示的代码。

package demo?

public class Demo5 {

public static void main(String[] args) {

synchronized (Demo5.class) {

dosomething()?

}

}

 

private static void dosomething() {

System.out.println("测试数据")?

}

}

技术分享图片

从上面我们可以看到只要有这两行汇编指令,那么其它的线程是进不来的。

下面抛出一个问题假如在线程内部抛异常了会怎么办

从上面的解析中我们可以看到,为了保证在方法异常完成时monitorenter和monitorexit指令依然可以正确配对执行,编译器会自动产生一个异常处理器,这个异常处理器声明可处理所有的异常,它的目的就是用来执行monitorexit指令。

如果一个同步方法执行期间抛出了异常,并且在方法内部无法处理此异常,那么这个同步方法所持有的管程将在异常抛到同步方法之外时自动释放。

这个问题等把多线程的笔记做完再说吧。

其它问题

多线程同步时其中一个线程出异常其它线程会不会继续执行?

线程代码中产生异常的话,那么这个线程的生命周期就结束了,这种情况称为线

程泄漏。

注意,只是这个线程的生命结束了,但其他的线程还是活着的。如果是代码有 BUG,那其他线程走到这一块估计也会挂掉的。

java 同步中的线程出现异常会放弃锁吗?会的,看下面的代码

package demo?

public class Demo5 {

public static void main(String[] args) throws InterruptedException {

final Object o = new Object()?

Runnable r1 = new Runnable() {

public void run() {

synchronized (o) {

throw new RuntimeException("throws")?

}

}

}?

Runnable r2 = new Runnable() {

public void run() {

synchronized (o) {

System.out.println("acquire lock")?

}

}

}?

new Thread(r1).start()? Thread.sleep(1000)?

new Thread(r2).start()?

}

}

技术分享图片

这个原因我们可以从指令中来看

技术分享图片

会直接跑出来来让后解锁接着往下走的。

ooo

以上是关于Jvm(50),指令集----同步指令的主要内容,如果未能解决你的问题,请参考以下文章

jvm原理(35)基于栈的指令集与基于寄存器的指令集详细比对&执行栈指令集实例剖析

jvm原理(35)基于栈的指令集与基于寄存器的指令集详细比对&执行栈指令集实例剖析

JVM指令集(指令码助记符功能描述)

Jvm(44),指令集----运算指令

jvm中篇-05-字节码指令集与解析

Jvm(47),指令集----控制转移指令