How is the synchronized method on AnyRef implemented?
Asked Answered
L

2

14

In Scala, there's a synchronized method on AnyRef which lets you synchronize on any object that extends AnyRef. However, it's abstract on AnyRef, and I couldn't figure out how it worked from grepping the scala source. It seems like it works by exploiting the synchronized keyword in Java. Is that the case?

Lezley answered 13/7, 2013 at 4:33 Comment(0)
P
32

1) AnyRef.synchronized is a magic method that doesn't exist in source code, but is injected into the compiler's symbol table on every startup of the compiler: Definitions.scala. There's a number of magic methods and classes, by the way (Definitions.scala).

2) If a method is wrapped in this.synchronized, the wrapping is dropped, and the method is internally annotated with a SYNCHRONIZED flag (UnCurry.scala), which is then mapped to JVM's `ACC_SYNCHRONIZED method access flag (GenASM.scala).

3) Other calls to synchronized are mapped onto the backend's primitive SYNCHRONIZED (backend/ScalaPrimitives.scala), which is later lowered into monitorenter/monitorexit (GenICode.scala #1, GenICode.scala #2).

Postorbital answered 13/7, 2013 at 7:29 Comment(0)
U
9

Just to add to the answer from Eugene, who knows the compiler by heart, here is a little scala console session.

The bottom line: the generated code is exactly identical to what you would get in java. There is no closure generated for the synchronized { ... } and not even a method call. Just a try/catch where at the beginning of the try there is a monitorenter bytecode (3) and both in the normal exit (9) an in the catch exit (12) there is a monitorexit. So there is no overhead involved in using synchronized in scala vs using it in java.

Note that most people agree that having dangerous low level thread synchronization constructs on every object is generally considered a bad idea that was only done for java compatibility.

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
Understanding answered 13/7, 2013 at 7:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.