2013-07-13 10 views
11

In Scala gibt es eine synchronisierte Methode für AnyRef, mit der Sie jedes Objekt synchronisieren können, das AnyRef erweitert. Allerdings ist es auf AnyRef abstrakt, und ich konnte nicht herausfinden, wie es funktionierte, die Scala-Quelle zu übermalen. Es scheint so, als ob es das synchronisierte Schlüsselwort in Java ausnutzt. Ist das der Fall?Wie wird die synchronisierte Methode auf AnyRef implementiert?

Antwort

25

1) AnyRef.synchronized ist eine magische Methode, die im Quellcode nicht existiert, aber bei jedem Start des Compilers in die Symboltabelle des Compilers eingefügt wird: Definitions.scala. Es gibt übrigens eine Reihe von magischen Methoden und Klassen().

2) Wenn eine Methode in this.synchronized gewickelt wird, wird die Verpackung fallen gelassen, und das Verfahren ist im Inneren mit einer SYNCHRONIZED Flag (UnCurry.scala) annotiert, die dann auf der JVM abgebildet wird `ACC_SYNCHRONIZED Methode Zugriffsflag (GenASM.scala).

3) Andere Anrufe synchronized werden auf das Primitive SYNCHRONIZED (backend/ScalaPrimitives.scala) Backend kartiert, die später in monitorenter/monitorexit abgesenkt (GenICode.scala #1, GenICode.scala #2).

8

Nur um die Antwort von Eugene, der den Compiler auswendig kennt, hinzuzufügen, hier ist eine kleine Scala-Konsolensitzung.

Die Quintessenz: Der generierte Code ist genau identisch mit dem, was Sie in Java erhalten würden. Für den synchronisierten {...} und nicht einmal für einen Methodenaufruf wird keine Sperrung generiert. Nur ein Versuch/catch, wo zu Beginn des Versuches gibt es einen monitorenter Bytecode (3) und beide in der normalen Ausgang (9) und in der Fang-Ausgang (12) gibt es einen Monitorexit. So gibt es keinen Aufwand bei der Verwendung synchronisiert in Scala vs Verwendung in Java.

Beachten Sie, dass die meisten Leute zustimmen, dass die Verwendung von gefährlichen Thread-Synchronisierungskonstrukten für niedrige Werte für jedes Objekt im Allgemeinen als eine schlechte Idee betrachtet wird, die nur für Java-Kompatibilität durchgeführt wurde.

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 
Verwandte Themen