kotlinvolatiledata-race

Understanding the working of volatile keyword


class OrderingTest {
   var x = 0
   var y = 0
   fun test() {
       thread {
           x = 1
           y = 1
       }
       thread {
           val a = y
           val b = x
           println("$a, $b")
       }
   }
}


I had this piece of code to explains the compiler re-ordering and race conditions. It had all possible outcomes:

1,0
0,1
0,0
1,1

But now considering this code

class OrderingTest {
   var x = 0
   @Volatile var y = 0
   fun test() {
       thread {
           x = 1
           y = 1
       }
       thread {
           val a = y
           val b = x
           println("$a, $b")
       }
   }
}


Can someone explain how does this adding volatile keyword to y makes 1,0 case impossible?


Solution

  • Forget about Kotlin for a bit, you have to go down to the JVM. What you are asking is about the memory model of the JVM and something that is called happens before.

    The very short answer is that when a variable has the volatile modifier, it triggers a happens before relation. This ensures that everything that happened up to that point on the thread will be visible to other threads.

    In your example, because y is marked as volatile, whenever the value of y changes, both the values of x and y will be visible to the other thread.

    I would recommend you to go a bit through the rabbit hole and read about the semantics of happens before (there are some videos on youtube about this too). I also recommend reading the excellent book Java Concurrency In Practice. Knowing this is crucial if you are going to be writing multithreaded software. Unfortunately most developers don't know about this (or safe publishing) and introduce all kinds of really hard to find bugs, so share what your find with your team!