AnyRef上的synchronized方法是如何实现的?

nny*_*thm 14 concurrency scala

在Scala中,AnyRef上有一个synchronized方法,它允许您在任何扩展AnyRef的对象上进行同步.但是,它在AnyRef上是抽象的,我无法弄清楚它是如何通过grepping scala源来实现的.看起来它的工作原理是利用Java中的synchronized关键字.是这样的吗?

Eug*_*ako 32

1)AnyRef.synchronized是源代码中不存在的魔术方法,但在编译器的每次启动时都会注入到编译器的符号表中:Definitions.scala.顺便说一下,有很多神奇的方法和类(Definitions.scala).

2)如果一个方法被包装this.synchronized,则包装被删除,并且该方法在内部注释一个SYNCHRONIZED标志(UnCurry.scala),然后将其映射到JVM的`ACC_SYNCHRONIZED方法访问标志(GenASM.scala).

3)其他调用synchronized被映射到后端的原语SYNCHRONIZED(后端/ ScalaPrimitives.scala),后来被降级为monitorenter/monitorexit(GenICode.scala#1,GenICode.scala#2).


Rüd*_*ehn 9

只是为了添加Eugene的答案,Eugene知道编译器,这是一个小scala控制台会话.

底线:生成的代码与您在java中获得的代码完全相同.同步{...}没有生成闭包,甚至没有方法调用.只是一个try/catch,在try的开始处有一个monitorenter字节码(3),并且在正常出口(9)和catch出口(12)中都存在monitorexit.因此,在scala中使用synchronized与在java中使用它不会产生任何开销.

请注意,大多数人都认为在每个对象上都有危险的低级线程同步构造通常被认为是一个坏主意,只是为了兼容java.

scala> class Test { def test { this.synchronized { } } }
defined class Test

scala> :javap -c Test
Compiled from "<console>"
public class Test extends java.lang.Object implements scala.ScalaObject{
public void test();
  Code:
   0:   aload_0
   1:   dup
   2:   astore_1
   3:   monitorenter
   4:   getstatic   #12; //Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
   7:   pop
   8:   aload_1
   9:   monitorexit
   10:  return
   11:  aload_1
   12:  monitorexit
   13:  athrow
  Exception table:
   from   to  target type
     4    10    11   any
Run Code Online (Sandbox Code Playgroud)