1

just had a look at class CopyOnWriteArrayList and I wondered why its get(...) method doesn't need any synchronization. The add(...) and set(...) methods change the underlying array in a mutex block using ReentrantLock. But get(...) just returns the raw underlying array without any synchronisation. Okay, the underlying array is declared volatile:

private volatile transient Object[] array;

But I don't see how using volatile makes any synchronisation redundant. It only prevents the reference stored in array from being cached by the compiler. If I understood why synchronisation is not needed here I could write my code with a little less lock contention than before ...

Thanks, Oliver

OlliP
  • 1,545
  • 11
  • 22
  • 6
    The name of the class is a hint. – Mark Rotteveel Apr 10 '13 at 13:11
  • 2
    possible duplicate of [How can CopyOnWriteArrayList be thread-safe?](http://stackoverflow.com/questions/2950871/how-can-copyonwritearraylist-be-thread-safe) – Mark Rotteveel Apr 10 '13 at 13:12
  • @Mark Rotteveel: You were right. Thanks. – OlliP Apr 10 '13 at 13:17
  • @MarkRotteveel I think the accepted answer in that thread misses an important point. The other answer is more accurate. – assylias Apr 10 '13 at 13:18
  • Duplicate of http://stackoverflow.com/questions/2950871/how-can-copyonwritearraylist-be-thread-safe as pointed out by Mark Rotteveel – OlliP Apr 10 '13 at 13:18
  • The real answer is that volatile since JDK1.5 is also atomic, see http://www.ibm.com/developerworks/library/j-jtp03304/ – OlliP Apr 10 '13 at 13:22
  • @OliverPlow not sure what you mean - volatile guarantees atomic `double` and `long` assignment but that's it. Other assignements are always atomic, regardless of volatility. – assylias Apr 10 '13 at 13:50
  • @OliverPlow you are getting atomicity and visibility confused. `volatile` guarantees visibility. Reference assignments are always atomic. – Boris the Spider Apr 10 '13 at 14:30

2 Answers2

1

The clue is in the name (as MarkRotteveel pointed out).

When any change is made the change is made in a separate Object[] then the whole lot is copied over - "copy on write".

As the internal Object[] is volatile when the reference is changed from the old Object[] to the new Object[] the change is picked up by all threads.

Boris the Spider
  • 59,842
  • 6
  • 106
  • 166
1

It uses a little "trick" - when the underlying array is changed, the sequence of events is:

  1. create a new array
  2. populate the new array
  3. change the reference held by the class to point to the new array

The third step writes to private volatile transient Object[] array; - due to volatile semantics, all changes made before step three are made visible.

So not only is the new reference visible, but the content of the new array is also made visible (that's the trick).

assylias
  • 321,522
  • 82
  • 660
  • 783