2

I am reading "Thinking in Java 4th Edition" right now and I have a question about one paragraph. (Page 832, in the Concurrency section)

volatile doesn’t work when the value of a field depends on its previous value (such as incrementing a counter), nor does it work on fields whose values are constrained by the values of other fields, such as the lower and upper bound of a Range class which must obey the constraint lower <= upper.

I don't understand what is "volatile doesn't work" and why keyword volatile has to consider other fields. Can you enlighten me or can you give me some example about it? Thank you very much!

ruanhao
  • 4,663
  • 6
  • 28
  • 43
  • I think this is related to the topic of volatile vs. atomic. See this post for more info: http://stackoverflow.com/questions/9749746/what-is-the-difference-between-atomic-volatile-synchronized – pczeus Mar 22 '16 at 02:05
  • 1
    I do not have the book but it seems that there is a context for "volatile doesn't work". Based on the content, the missing part here is something like: _**"Volatile can help in concurrency for some situations, but " ...**_ _volatile doesn’t work when the value of a field depends on its previous value ....._ With such context, your quoted paragraph will make sense – Adrian Shum Mar 22 '16 at 03:05

1 Answers1

2

volatile doesn’t work when the value of a field depends on its previous value

volatile int i;

public void bar() {
  if (i == 0) 
    i = 1;
  else 
    i = 2;
}

Considering the above example, if there are two threads which run boo() and check that i is 0, both threads then set i to 1. However, i is expected to be incremented to 2. Volatile cannot guarantee atomicity here.


nor does it work on fields whose values are constrained by the values of other fields, such as the lower and upper bound of a Range class which must obey the constraint lower <= upper

public class Range {
    private int lower, upper;

    public void setLower(int value) { 
        if (value <= upper) 
          lower = value;
    }

    public void setUpper(int value) { 
        if (value >= lower)                
          upper = value;
    }
}

In this case, making the lower and upper fields volatile cannot guarantee thread-safe. For example, assume the initial values of lower and upper are 1 and 10 respectively. If there are two threads which run setLower(6) and setUpper(4) at the same time, both of them can pass the condition checks which results in an invalid range 6 to 4. So synchronization is needed here to guarantee thread-safe.

Community
  • 1
  • 1
Siu
  • 1,422
  • 1
  • 12
  • 17