Does a write to a volatile var make previous writes visible?

Another question from Learning Concurrent Programming in Scala - Second Edition (Search | Packt Subscription)

Is this statement true:
“When writing to a volatile var, then that write and all previous writes in that thread are guaranteed visible to other threads.”

I’ve derived that from…

object Volatile extends App {
  case class Page(txt: String, var position: Int)

  def thread(body: =>Unit): Thread = {
    val t = new Thread {
      override def run() = body
    }
    t.start()
    t
  }

  val pages = for (i <- 1 to 5) yield
    new Page("Na" * (100 - 20 * i) + " Batman!", -1)
  @volatile var found = false
  for (p <- pages) yield thread {
    var i = 0
    while (i < p.txt.length && !found)
      if (p.txt(i) == '!') {
        p.position = i
        found = true
      } else i += 1
  }
  while (!found) {}
  log(s"results: ${pages.map(_.position)}")
}

and some of the associated text…

Note that a write to position occurs before the write to found in the spawned threads, which in turn occurs before reading found in the main thread. This means that the main thread always sees the write of the thread that set found, and hence prints at least one position other than -1.

I had assumed that volatile was a per var before reading this and I just wanted to check that I understood it correctly.

To understand concurrency concepts like this in Scala you’ll find that it all rides on the underlying guarantees provided by the JVM and the Java Memory Model. In a simplification, when talking about volatile you can think of it as “flush writes from thread’s “local” state into the shared global memory, accessible by all other threads, and invalidate their copies of that data, in case they had any”.

While old, this article could help you about your specific volatile question: https://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile

Another excellent reference is the JMM Cookbook: http://g.oswego.edu/dl/jmm/cookbook.html

Hope this helps

Thanks for the links, that helped a lot!

For other readers, I’ve so far visited the first link and it makes it clear that volatile does enable other threads to read all the writes that occurred before the write to the volatile var; however, only after the other thread reads from that volatile var.

Each read or write of a volatile field acts like “half” a synchronization, for purposes of visibility.

The linked section is very short and clearly written so I advise anyone curious to give it a read.

1 Like