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
Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object's variables are done through synchronized methods.
When we use a synchronized block, Java internally uses a monitor, also known as monitor lock or intrinsic lock, to provide synchronization. These monitors are bound to an object; therefore, all synchronized blocks of the same object can have only one thread executing them at the same time.
static methods can be synchronized. But you have one lock per class. when the java class is loaded coresponding java.
If you synchronize a code block within that method then more than one thread can execute the method simultaneously, but only one thread can enter the synchronized block at a time. From this we can conclude that synchronizing on the smallest possible code block required is the most efficient way to do it.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With