当前位置: 首页 > 知识库问答 >
问题:

同步块可以简化为字节码级别的Try-Finally块吗?

华君浩
2023-03-14

在为类似Java的语言编写自己的编译器时,我在编译synchronized blocks时遇到了麻烦。我想出了以下想法来将它们简化为try-finally块:

synchonized (obj) {
     statements...
}

可替换为

Object _lock = obj
_monitorEnter(lock)
try {
    statements...
}
finally {
    _monitorExit(lock)
}

编辑

我的实现以前对主体中的returnthrow语句进行了一些特殊处理。基本上,它将在每个*returnthrow指令之前手动加载所有lock变量和monitorexit变量。这是由finally块处理的,还是我仍然需要这些检查?

共有1个答案

宋成天
2023-03-14

你的假设是正确的。Java语言中的synchronized块是通过monitorentermonitorexit指令实现的。您可以在这里查看JVM规范的详细信息。

Java虚拟机中的同步是通过监视器进入和退出来实现的,可以是显式的(通过使用monitorenter和monitorexit指令),也可以是隐式的(通过方法调用和返回指令)。

编译器生成的字节码将处理在synchronized正文中抛出的所有异常,因此您的try-finally方法在这里可以很好地工作。

finally语句的规范没有说明任何有关释放监视器的内容。第一个链接中提供的示例显示了包装在synchronized块中的简单方法的字节码。如您所见,处理任何可能的异常以确保monitorexit指令执行。您应该在编译器中实现相同的行为(编写将在finally语句中释放monitor的代码)。

void onlyMe(Foo f) {
    synchronized(f) {
        doSomething();
    }
}

Method void onlyMe(Foo)
0   aload_1             // Push f
1   dup                 // Duplicate it on the stack
2   astore_2            // Store duplicate in local variable 2
3   monitorenter        // Enter the monitor associated with f
4   aload_0             // Holding the monitor, pass this and...
5   invokevirtual #5    // ...call Example.doSomething()V
8   aload_2             // Push local variable 2 (f)
9   monitorexit         // Exit the monitor associated with f
10  goto 18             // Complete the method normally
13  astore_3            // In case of any throw, end up here
14  aload_2             // Push local variable 2 (f)
15  monitorexit         // Be sure to exit the monitor!
16  aload_3             // Push thrown value...
17  athrow              // ...and rethrow value to the invoker
18  return              // Return in the normal case
Exception table:
From    To      Target      Type
4       10      13          any
13      16      13          any
 类似资料:
  • 运行显然会导致,但运行不会(程序似乎只是无限期运行)。这是为什么?

  • 本文向大家介绍说明PowerShell中的Try / Catch / Finally块,包括了说明PowerShell中的Try / Catch / Finally块的使用技巧和注意事项,需要的朋友参考一下 PowerShell中的Try / Catch块用于处理脚本中产生的错误。具体而言,错误应该是终止错误。在最后在PowerShell中块不是强制性的,每次沿写try / catch语句,但它会

  • 问题内容: 根据Java语言规范的第§14.20.2节 通过首先执行try块来执行带有finally块的try语句。然后有一个选择: 如果try块的执行正常完成,则执行finally块,然后可以选择: 如果finally块正常完成,则try语句正常完成。 如果finally块由于原因S突然完成,则try语句由于原因S突然完成 如果我正确地解释了它,那么在执行try块之后最终会被调用,但是所有这些如

  • 主要内容:1 什么是Java同步代码块,2 Java同步代码块的要点,3 Java同步代码块的语法,4 Java同步代码块的例子1,5 Java同步代码块的例子21 什么是Java同步代码块 同步代码块可用于对方法的任何特定资源执行同步。 假设您的方法中有50行代码,但是您只想同步5行,则可以使用synchronized代码块。 如果将方法的所有代码放在同步代码块中,它的效果与同步方法相同。 2 Java同步代码块的要点 同步代码块用于锁定任何共享资源的对象。 同步代码块的范围小于该方法。 3 

  • 假设以下两种计数器实现: 乍一看,原子应该更快、更具可扩展性。我相信他们是的。但是它们始终比同步块快吗?或者当该规则被打破时,存在某些情况(例如SMP/单CPU机器、不同的CPU ISA、操作系统等)?