1. ホーム
  2. scala

[解決済み] Scalaでsynchronizedを使うには?

2022-02-03 09:48:59

質問

次のようなコードがあります。

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

解決方法は?

が必要ない場合は 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 .

要するに、Scalaのフォーマットは(ブロックは値を返すことができる)。

this.synchronized {
   ctr = ctr + 1
   ctr
}

これは、javaの

synchronized(this) {
   return ++ctr;   
}

Scala には synchronized メソッドで、ブロックだけです。

編集

下のコメントからの質問にお答えします。 synchronized をメソッドとして使用することができます。 AnyRef :

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

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

というように、オブジェクトのメソッドを呼び出しているのです。 toStringthis.toString .