2013-07-13 17 views
11

Scala'da, AnyRef üzerinde AnyRef'i genişleten herhangi bir nesneyle senkronize etmenizi sağlayan senkronize bir yöntem var. Ancak, AnyRef üzerinde özet ve ben scala kaynağına grepping çalıştı nasıl anlayamadım. Java'daki senkronize anahtar sözcüğünü kullanarak çalışır gibi görünüyor. Bu dava mı?AnyRef'te senkronize yöntem nasıl uygulanır?

cevap

25

1) AnyRef.synchronized, kaynak kodunda bulunmayan, ancak derleyicinin her başlatılırken derleyicinin sembol tablosuna enjekte edilen sihirli bir yöntemdir: Definitions.scala. Bu arada, bir dizi sihirli yöntem ve sınıf var (Definitions.scala). Bir yöntem this.synchronized sarılı ise

2), ambalaj bırakılır ve yöntem dahili sonra JVM `ACC_SYNCHRONIZED yöntem erişim bayrağı (GenASM.scala) eşlenen bir SYNCHRONIZED bayrağı (UnCurry.scala) ile açıklandı. synchronized için

3) Diğer aramalar üzerine eşlemlenmektedir sonra monitorenter/monitorexit (GenICode.scala #1, GenICode.scala #2) içine indirilir arka uç ilkel SYNCHRONIZED (backend/ScalaPrimitives.scala).

8

Derleyiciyi kalpten tanıyan Eugene'nin yanıtına eklemek için, burada küçük bir scala konsol oturumu var.

Alt satır: oluşturulan kod, java'da alacağınızla tam olarak aynıdır. Senkronize edilmiş {...} için bir kapanma yoktur ve bir yöntem çağrısı bile yoktur. Denemenin başlangıcında bir monitör bayt kodu (3) ve her ikisi de normal çıkışta (9), çıkış çıkışında (12) bir monitorexit olduğu bir deneyin/yakalayın. Bu nedenle, scala'da senkronize olarak kullanıldığında vs java'da kullanıldığında hiçbir ek yük bulunmamaktadır.

Çoğu insan, her nesnede tehlikeli düzeyde düşük düzeyli iş parçacığı senkronizasyonu oluşturmanın genellikle yalnızca java uyumluluğu için yapılan kötü bir fikir olarak kabul edildiğini kabul eder.

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