Как использовать синхронизированный в Scala?

У меня есть следующий код:

object Foo {
 private var ctr = 0L

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

Требование состоит в том, что ctr должно использоваться только один раз. В моем случае одно и то же значение ctr используется повторно. Моя теория заключается в том, что это происходит потому, что Foo.bar вызывается одновременно в разных потоках (это единственный вывод, который я мог бы сделать). В качестве исправления я имею следующий модифицированный код.

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

Я не нашел хорошего руководства для использования synchronized метода в Scala. Может ли кто-нибудь сообщить мне, если вышеуказанный код исправит мою проблему.

EDIT: Основываясь на комментариях ниже, я думаю, что AtomicLong - лучшее решение для меня:

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

Ответы

Ответ 1

Если вы не хотите AtomicInteger, вот как использовать synchronized

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

Вам необходимо выполнить синхронизацию на каком-либо объекте. В этом случае на вашем текущем объекте, который this.

Это эквивалент java

synchronized(this) {
   return ++ctr;   
}

Scala не имеет методов synchronized в качестве java, только блоки.

Изменить

Чтобы ответить на вопрос из комментария ниже: synchronized можно использовать как метод из класса AnyRef:

https://www.scala-lang.org/api/current/scala/AnyRef.html

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

так что вы вызываете метод вашего объекта, как вы это делаете toString и this.toString.