Reputation: 18024
I have the following code:
object Foo {
private var ctr = 0L
def bar = {
ctr = ctr + 1
// do something with ctr
}
}
The requirement is that a ctr
value should be used only once. In my case the same value of ctr
is getting reused. My theory is that this happens because Foo.bar
is called concurrently in different threads (this is the only conclusion I could draw). I have the following modified code as a fix.
object Foo {
private var ctr = 0L
def getCtr = synchronized{
ctr = ctr + 1
ctr
}
def bar = {
val currCtr = getCtr
// do something with currCtr
}
}
I could not find a good guide for using the synchronized
method in Scala. Can anyone let me know if the above code will fix my problem.
EDIT: Based on the comments below, I think AtomicLong
is the best solution for me:
import java.util.concurrent.atomic.AtomicLong
private val ctr = new AtomicLong
def getCtr = ctr.incrementAndGet
Upvotes: 37
Views: 53849
Reputation: 8663
If you don't want an AtomicInteger
, here is how to use synchronized
object Foo {
private var ctr = 0L
def getCtr = this.synchronized {
ctr = ctr + 1
ctr
}
def bar = {
val currCtr = getCtr
// do something with currCtr
}
}
You need to synchronize on some object. In this case on your current object which is this
.
In short: Scala's format is (and the block can return a value)
this.synchronized {
ctr = ctr + 1
ctr
}
It is equivalent of java's
synchronized(this) {
return ++ctr;
}
Scala does not have synchronized
methods as java, just blocks.
Edit
To answer the question from comment below: synchronized
can be used as a method from class AnyRef
:
https://www.scala-lang.org/api/current/scala/AnyRef.html
final def synchronized[T0](arg0: ⇒ T0): T0
so you are calling a method of your object, just like you would do toString
and this.toString
.
Upvotes: 61