5

I am using a java.util.concurrent.ConcurrentLinkedQueue object to pass data between threads.

Should I declare my references volatile?

Robin Green
  • 32,079
  • 16
  • 104
  • 187
JLindsey
  • 700
  • 2
  • 7
  • 14
  • 1
    It is worth noting that the object doesn't change throughout execution, so maybe `final` is more appropriate? – JLindsey Dec 31 '13 at 15:01
  • 1
    Setting the queue volatile doesn't make references inside the queue volatile – Sami Korhonen Dec 31 '13 at 15:02
  • 1
    `volatile` like `final` doesn't confer anything on the object referenced, only the reference itself. You would only make it volatile if you plan to replace the whole queue object. – Peter Lawrey Dec 31 '13 at 15:11

3 Answers3

5

In short, no.

The value that your queue variable contains is a reference to the queue. This value won't change unless you reassign the queue like myQueue = otherQueue; If all you are doing afer you create the queue is putting things in and taking things out then it doesn't matter if a thread has a cached value because the value (the reference to the queue) never changes.

It's good practice to make all variables final unless you need it to not be final.

Mike B
  • 5,390
  • 2
  • 23
  • 45
  • Perfect. That helps quite a bit. I'm not changing my reference (like you said), so it makes sense – JLindsey Dec 31 '13 at 15:06
  • 1
    This is not quite true. The value does change when the variable is first assigned - even if it is declared `final`. It changes from `null`. This only matters, though, if the value is observable to any other threads before the constructor and any instance initialisers have finished executing. – Robin Green Dec 31 '13 at 15:09
  • @Robert Green: A constructor cannot be executed concurrently, can it? And before it returned, nothing can see the object, can it? – Sibbo Dec 31 '13 at 15:12
  • 1
    @Sibbo The JLS doesn't specify whether or not the constructor can finish before the object is published. That being said, it may appear the constructor hasn't finished because the fields that have already been declared in the constructor may have not been published to other processor/threads. – John Vint Dec 31 '13 at 15:16
  • @Sibbo "nothing can see the object" - false. That's why doublecheck locking idiom for singletone utilizes volatile for the instance, another thread may see a reference to the constructed object which has not fully initilized yet, volatile fixes the issue. However, if the fields are final there is some guarantee, but not sure those guarantees are valid for ALL JVM impls. – Vadim Kirilchuk Feb 12 '21 at 10:51
1

No, since you are always using the same queue. Volatile means, that the value of a variable in memory will always be the same for every processor. Note that variables that are stored in a register will not be synchronised, even if you declare the variable as volatile.

Sibbo
  • 3,796
  • 2
  • 23
  • 41
  • 3
    So, `volatile` applies to the reference, and is used in situations where the reference can change? – JLindsey Dec 31 '13 at 15:02
  • 3
    Yes. And it can also be used for concurrent reads/writes of primitive types (int, double, ...) – Sibbo Dec 31 '13 at 15:07
1

If you can declare it final, then declare it final. If you cannot, declare it volatile.

Declaring it volatile has no effects on the inner structure of the Queue though. It only adds additional synchronization when assigning the a new ConcurrentLinkedQueue()

John Vint
  • 39,695
  • 7
  • 78
  • 108