2016-01-19 8 views
5

Ich habe den folgenden Code:Wie synchron in Scala zu verwenden?

object Foo { 
private var ctr = 0L 

def bar = { 
    ctr = ctr + 1 
    // do something with ctr 
} 
} 

Voraussetzung ist, dass ein ctr Wert sollte nur einmal verwendet werden. In meinem Fall wird der gleiche Wert von ctr wiederverwendet. Meine Theorie ist, dass dies passiert, weil Foo.bar gleichzeitig in verschiedenen Threads aufgerufen wird (dies ist die einzige Schlussfolgerung, die ich zeichnen konnte). Ich habe den folgenden modifizierten Code als Update.

object Foo { 
private var ctr = 0L 
def getCtr = synchronized{ 
    ctr = ctr + 1 
    ctr 
} 
def bar = { 
    val currCtr = getCtr 
    // do something with currCtr 
} 
} 

konnte ich nicht eine gute Anleitung für die Verwendung der synchronized Methode in Scala finden. Kann mir jemand mitteilen, ob der obige Code mein Problem beheben wird.

EDIT: Basierend auf den Kommentaren unten, ich glaube AtomicLong die beste Lösung für mich ist:

import java.util.concurrent.atomic.AtomicLong 
private val ctr = new AtomicLong 
def getCtr = ctr.incrementAndGet 
+1

Haben Sie sich schon einmal https://twitter.github.io/scala_school/concurrency.html angesehen? Sie könnten auch eine AtomicLong verwenden. – Markon

+2

Ich würde das Problem umgehen und einen 'AtomicInteger' verwenden. Diese sind für gleichzeitige Zähler vorgesehen. – Thilo

+2

+1. Ich verstehe die Betonung auf höherer Gleichzeitigkeit (Futures, Schauspieler, etc.), aber es ist schade, dass definitive Scala-Bücher nicht einmal _mention_ 'obj.synchronized'-Syntax haben. –

Antwort

15

Wenn Sie nicht AtomicInteger wollen, gibt es, wie synchronized verwenden

object Foo { 
private var ctr = 0L 
def getCtr = this.synchronized { 
    ctr = ctr + 1 
    ctr 
} 
def bar = { 
    val currCtr = getCtr 
    // do something with currCtr 
    } 
} 

Sie müssen auf ein Objekt synchronisieren. In diesem Fall auf Ihrem aktuellen Objekt, das ist this.

Es entspricht der

synchronized(this) { 
    return ctr++; 
} 

Scala Java nicht synchronized Methoden wie Java hat, nur wenige Blocks.

bearbeiten

die Frage von Kommentar unten zu beantworten: Ihre

http://www.scala-lang.org/api/current/index.html#scala.AnyRef

final def synchronized[T0](arg0: ⇒ T0): T0 

so rufen Sie eine Methode: synchronized kann AnyRef als Methode aus der Klasse verwendet werden Objekt, genau wie Sie würden toString und this.toString tun.

+0

Was passiert, wenn ich 'this' überspringe? Der Code kompiliert und scheint sich korrekt zu verhalten. – Jus12

+0

@ Jus12 Ich bearbeitete meine Antwort –

+3

Beachten Sie, dass im Gegensatz zu 'toString' es nicht _actually_ eine Methode auf' AnyRef' ist, der Compiler nur vorgibt es ist. –

Verwandte Themen