2

I know using volatile keyword in Java we get some kind of weak synchronization (It allows visibility updates but do not provide actual locking). Is there any situation where volatile should be given preference over actual locking in implementing concurrent programs. A somewhat similar question is there on SO which says volatile as a synchronization mechanism but that was tagged to C#.

Community
  • 1
  • 1
Inquisitive
  • 7,476
  • 14
  • 50
  • 61
  • [This](http://stackoverflow.com/a/5953618/102441) answer explains why volatile is not always good enough. That applies to Java as much as C#. – Eric Jun 30 '12 at 14:24

3 Answers3

3

If the shared state consists in a single field, and you don't use any get-and-set construct (like i++ for example) to assign it, then volatile is good enough. Most of the volatile usages can be replaced by the use of AtomicXxx types, though (which provide atomic get-and-set operations).

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
2

In short, you should prefer to avoid locks wherever they are not necessary since locks expose your program to deadlocks and deter performance by excluding concurrency from critical parts of code. So, whenever the situation permits, by all means rely on volatile; if all you additionally need is atomic two-step operations like compare-and-swap, use AtomicReference. Fall back to synchronized only for the scenarios where this is the only option. For example, if you need to lazily initialize a heavy object, you'll need locks to prevent double initialization—but again, not to fetch the already initialized instance (double-check idiom).

Community
  • 1
  • 1
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • 3
    OTOH, volatile is a not-well-understood keyword, and in many many situations, synchronization doesn't cause any significant performance overhead. Using high-level APIs (blocking queues, Atomics, Semaphores, concurrent collections, etc.) is, most of the time, the best and safest technique. – JB Nizet Jun 30 '12 at 14:30
  • 1
    That said, many of the high-level APIs use `volatile` internally. – Louis Wasserman Jun 30 '12 at 14:33
  • ... and fundamentally build on `volatile` guarantees. Javadoc of many a`java.util.concurrent` class explicitly specifies its semantics "as if writing/reading a `volatile`". – Marko Topolnik Jun 30 '12 at 14:56
  • @JBNizet I would add, unfortunately not well-understood, since it is a really simple concept. I think it's only because the semantics as of Java 1.5 still haven't caught on (and it's been around close to a decade now). – Marko Topolnik Jun 30 '12 at 14:58
  • @seh Thanks for the em-dash, I need to start using it... (the en-dash, too). – Marko Topolnik Jun 30 '12 at 15:12
  • As far as "not causing any significant performance overhead," if you don't *need* the synchronization, then it's nothing but overhead. The hard part is knowing when you do and don't need it. – seh Jun 30 '12 at 18:26
  • @MarkoTopolnik Please give a link to the double check idiom. It will be useful for the readers of this post. – Inquisitive Jul 01 '12 at 13:22
  • The issue that @JBNizet, Louis and myself have, is in finding many circumstances, in real-world, complex apps, where 'volatile' is actually useful for inter-thread comms outside the internal structure of queues etc objects. that are usually provided by the OS and language libraries. I'm prepared to be enlightened, however, so if anyone has an example, outside the construction of higher-level synchro objects or trivial integer-incrementers, please suggest one:) – Martin James Jul 01 '12 at 15:57
  • @MartinJames `volatile` is very useful on its own in any case where you can completely set up an immutable state involving arbitrarily many objects and then atomically publish it as a whole to other threads. Clojure, maybe an exotic example, is fundamentally based on lock-free, copy-on-write, shared-data structures. For coordination they don't need anything more than the equivalent of `AtomicReference`s. – Marko Topolnik Jul 01 '12 at 16:13
  • @MartinJames I should add that in the everyday world of mutability in Java there is indeed much less opportunity for atomic operations than in the Clojure world. It is a thing that needs to be designed in from the start. – Marko Topolnik Jul 01 '12 at 16:24
0

Volatile guarantees that all threads will see the last write of a variable by any other thread, that's it. There's no synchronization involved. If you synchronize both read and write method of an instance variable, then you don't have to make that variable volatile (all threads will see the most recent write).

Alper Akture
  • 2,445
  • 1
  • 30
  • 44