如何在Scala中使用synchronized?

Jus*_*s12 20 scala

我有以下代码:

object Foo {
 private var ctr = 0L

 def bar = {
   ctr = ctr + 1
   // do something with ctr
 }
}
Run Code Online (Sandbox Code Playgroud)

要求是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
 }
}
Run Code Online (Sandbox Code Playgroud)

我找不到synchronized在Scala中使用该方法的好指南.任何人都可以告诉我,如果上述代码将解决我的问题.

编辑:基于以下评论,我认为AtomicLong对我来说是最好的解决方案:

import java.util.concurrent.atomic.AtomicLong
private val ctr = new AtomicLong
def getCtr = ctr.incrementAndGet
Run Code Online (Sandbox Code Playgroud)

Łuk*_*asz 35

如果你不想要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
  }
}
Run Code Online (Sandbox Code Playgroud)

您需要在某个对象上进行同步.在这种情况下,你当前的对象是this.

它相当于java的

synchronized(this) {
   return ++ctr;   
}
Run Code Online (Sandbox Code Playgroud)

Scala没有synchronized像java 这样的方法,只是块.

编辑

要回答以下评论中的问题:synchronized可以用作类中的方法AnyRef:

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

final def synchronized[T0](arg0: ? T0): T0
Run Code Online (Sandbox Code Playgroud)

所以你在呼唤你的对象的方法,就像你会做toStringthis.toString.

  • 请注意,与`toString`不同,它不是_actually_在AnyRef`上的方法,编译器只是假装它. (3认同)
  • 如果我跳过“ this”会怎样?该代码可以编译,并且似乎可以正常运行。 (2认同)
  • 在`object` 中,`this.synchronized {...}` 和`synchronized {...}` 是否相同? (2认同)