2016-01-19 15 views
5

Mam następujący kod:Jak używać synchronizacji w Scali?

object Foo { 
private var ctr = 0L 

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

wymóg jest, że wartość ctr powinny być używane tylko raz. W moim przypadku ta sama wartość ctr jest ponownie wykorzystywana. Moja teoria mówi, że dzieje się tak dlatego, że Foo.bar jest wywoływany jednocześnie w różnych wątkach (jest to jedyny wniosek, który mogłem wyciągnąć). Mam następujący zmodyfikowany kod jako poprawkę.

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

nie mogłem znaleźć dobrego przewodnika metodą w Scala synchronized. Czy ktoś może dać mi znać, jeśli powyższy kod naprawi mój problem.

EDIT: Na podstawie poniższych uwag, myślę AtomicLong jest najlepszym rozwiązaniem dla mnie:

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

Czy obejrzałeś już to https://twitter.github.io/scala_school/concurrency.html? Możesz także użyć AtomicLong. – Markon

+2

Zrobiłem krok po kroku i użyłem 'AtomicInteger'. Te są wykonane dla współbieżnych liczników. – Thilo

+2

+1. Rozumiem nacisk kładziony na współbieżność wyższego poziomu (futures, aktorzy, itp.), Ale jest to szkoda, że ​​książki Scala nie zawierają nawet składni _mention_ 'obj.synchronized'. –

Odpowiedz

15

Jeśli nie chcesz AtomicInteger istnieje sposób korzystania synchronized

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

Musisz zsynchronizować jakiś obiekt. W tym przypadku na bieżącym obiekcie, który jest this.

Jest odpowiednikiem Java

synchronized(this) { 
    return ctr++; 
} 

Scala nie ma synchronized metody jak Java, tylko bloki.

Edit

Aby odpowiedzieć na pytanie z komentarza poniżej: synchronized może być stosowana jako metoda z klasy AnyRef:

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

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

więc dzwonisz sposób swoje obiekt, tak jak zrobiłbyś toString i this.toString.

+0

Co się stanie, jeśli pominę "to"? Kod się kompiluje i wydaje się zachowywać poprawnie. – Jus12

+0

@ Jus12 Edytowałem moją odpowiedź –

+3

Zauważ, że w przeciwieństwie do 'toString' nie jest _w rzeczywistości metodą na' AnyRef', kompilator tylko udaje, że jest. –

Powiązane problemy