0

Consider the following code:

var currentState: Map[Int, Int] = _

If multiple threads are updating the same variable with the same value, is there any issue on the JVM? Since currentState is just a pointer, there is no heavy operation, and locking is not required since it's the same value.

Is that correct?

8
  • 1
    You will eventually hit a race condition and will corrupt the real data. Use a concurrent safe data structure like an AtomicReference or a cats.effect.Ref Commented Aug 2, 2023 at 15:33
  • 1
    Does this answer your question? Scala - Mutable thread safe collections Commented Aug 2, 2023 at 15:44
  • I'm not sure why I need an Atomic or Synchronized data structure. I'm updating the data structure every 5 minutes, let's say. I do not care which thread will update the point first, since it's not copying any data but updating the reference. Also, all the threads will update the currentState to the same value.
    – Zvi Mints
    Commented Aug 2, 2023 at 18:34
  • 2
    stackoverflow.com/questions/3964211/… - the primary reason to use atomic reference is usually to make sure that the value you override, is the same value you read and used to compute your new value. Otherwise you might have a situation: thread 1 reads value 1 -> thread 2 reads value 1 -> thread 1 writes value 2 made of value 1, thread 2 writes value 3 made of value 1 - the fact that thread 1 made an update is lost. If you think that atomic ref is not needed, go ahead. /1 Commented Aug 2, 2023 at 20:04
  • But if your argument is that update is made every 20 minutes or so... then there is no argument against using it since the overhead would be non-existent, and it would save you ass in those rare cases when it was not 20 minutes between updates but e.g. 20 millis. /2 Commented Aug 2, 2023 at 20:04

1 Answer 1

5

Reads and writes to references are always atomic in java, so, at least, you are not risking to crash your JVM by doing this.

However:

(1) What you write to that var in one thread other threads are not guaranteed to see until both writing and reading threads hit a memory barrier (which are not actually mentioned anywhere in the JLS, and are therefore implementation-specific). From a practical standpoint, I would say, it is sort of unusual to expect an active thread in a modern JVM application to not hit a memory barrier every few milliseconds or so, but still, it is not impossible for other threads to no see the value your thread has written for hours. This is pretty easily fixable by adding @volatile annotation to your var - that ensures that the write is committed immediately, and every read that happens after that write will see the new value. But ...

(2) Seeing var in scala code is bad enough for a reader in terms of cognitive load. The issue, also known as "code smell" is that someone, even moderately used to scala, who's reading this code is going to pause and waste cycles figuring out "why we need a var here?", and "is it going to cause problems"? I won't get into much more details on this, because mutability is not a topic here, just trust me that that is bad enough. But what you have is not just a var, it's a var, that is externally accessible, and concurrently modified by multiple threads.

Long story short, just give the reader of you code a break, and use AtomicReference. It has literally no cost (compared to using @volatile, which is a bit costly, but only a little, and I don't see how you can get around it anyway), just pure benefit.

Not the answer you're looking for? Browse other questions tagged or ask your own question.