Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>According to <a href="http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html" rel="nofollow noreferrer">the relevant Java Tutorial</a>, </p> <blockquote> <p>We have already seen that an increment expression, such as <code>c++</code>, does not describe an atomic action. Even very simple expressions can define complex actions that can decompose into other actions. However, there are actions you can specify that are atomic:</p> <ul> <li>Reads and writes are atomic for reference variables and for most primitive variables (all types except <code>long</code> and <code>double</code>).</li> <li>Reads and writes are atomic for all variables declared <code>volatile</code> (<em>including</em> <code>long</code> and <code>double</code> variables).</li> </ul> </blockquote> <p>This is reaffirmed by <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7" rel="nofollow noreferrer">Section §17.7 of the Java Language Specification</a></p> <blockquote> <p>Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.</p> </blockquote> <p>It appears that you can indeed rely on reference access being atomic; however, recognize that this does <em>not</em> ensure that all readers will read an updated value for <code>global</code> after this write -- i.e. there is no memory ordering guarantee here.</p> <p>If you use an implicit lock via <code>synchronized</code> on all access to <code>global</code>, then you can forge some memory consistency here... but it might be better to use an alternative approach.</p> <p>You also appear to want the collection in <code>global</code> to remain immutable... luckily, there is <a href="http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#unmodifiableSet(java.util.Set)" rel="nofollow noreferrer"><code>Collections.unmodifiableSet</code></a> which you can use to enforce this. As an example, you should likely do something like the following...</p> <pre><code>private volatile Collection global = Collections.unmodifiableSet(new HashSet()); </code></pre> <p>... that, or using <code>AtomicReference</code>,</p> <pre><code>private AtomicReference&lt;Collection&gt; global = new AtomicReference&lt;&gt;(Collections.unmodifiableSet(new HashSet())); </code></pre> <p>You would then use <code>Collections.unmodifiableSet</code> for your modified copies as well.</p> <hr> <pre><code>// ... All reads are done through a reference copy like: // Collection copy = global; // for (Object elm: copy) {... // so the global reference being updated half way through should have no impact </code></pre> <p>You should know that making a copy here is redundant, as internally <code>for (Object elm : global)</code> creates an <code>Iterator</code> as follows...</p> <pre><code>final Iterator it = global.iterator(); while (it.hasNext()) { Object elm = it.next(); } </code></pre> <p>There is therefore no chance of switching to an entirely different value for <code>global</code> in the midst of reading.</p> <hr> <p>All that aside, I agree with the <a href="https://stackoverflow.com/questions/11963972/in-java-can-i-depend-on-reference-assignment-being-atomic-to-implement-copy-on-w/11964034#comment15944871_11963972">sentiment expressed by DaoWen</a>... is there any reason you're rolling your own data structure here when there may be <a href="http://docs.oracle.com/javase/tutorial/essential/concurrency/collections.html" rel="nofollow noreferrer">an alternative available in <code>java.util.concurrent</code></a>? I figured maybe you're dealing with an older Java, since you use raw types, but it won't hurt to ask. </p> <p>You can find copy-on-write collection semantics provided by <a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CopyOnWriteArrayList.html" rel="nofollow noreferrer"><code>CopyOnWriteArrayList</code></a>, or its cousin <a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CopyOnWriteArraySet.html" rel="nofollow noreferrer"><code>CopyOnWriteArraySet</code></a> (which implements a <code>Set</code> using the former).</p> <hr> <p>Also <a href="https://stackoverflow.com/a/11964129/591495">suggested by DaoWen</a>, have you considered using a <a href="http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ConcurrentHashMap.html" rel="nofollow noreferrer"><code>ConcurrentHashMap</code></a>? They guarantee that using a <code>for</code> loop as you've done in your example will be consistent.</p> <blockquote> <p>Similarly, Iterators and Enumerations return elements reflecting the state of the hash table at some point at or since the creation of the iterator/enumeration.</p> </blockquote> <p>Internally, an <code>Iterator</code> is used for enhanced <code>for</code> over an <code>Iterable</code>.</p> <p>You can craft a <code>Set</code> from this by utilizing <a href="http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#newSetFromMap(java.util.Map)" rel="nofollow noreferrer"><code>Collections.newSetFromMap</code></a> like follows:</p> <pre><code>final Set&lt;E&gt; safeSet = Collections.newSetFromMap(new ConcurrentHashMap&lt;E, Boolean&gt;()); ... /* guaranteed to reflect the state of the set at read-time */ for (final E elem : safeSet) { ... } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload