title: Is iteration via Collections.synchronizedSet(...).forEach() guaranteed to be thread safe?
body: <p>As we know, iterating over a concurrent collection is not thread safe by default, so one cannot use:</p>
  
  <pre><code>Set&lt;E&gt; set = Collections.synchronizedSet(new HashSet&lt;&gt;());
  //fill with data
  for (E e : set) {
      process(e);
  }
  </code></pre>
  
  <p>This happens as data may be added during iteration, because there is no exclusive lock on <code>set</code>.</p>
  
  <p>This is describe in the <a href="http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedSet-java.util.Set-">javadoc</a> of <code>Collections.synchronizedSet</code>:</p>
  
  <blockquote>
    <p>public static  Set synchronizedSet(Set s)</p>
    
    <p>Returns a synchronized (thread-safe) set backed by the specified set. In order to guarantee serial access, it is critical that all access to the backing set is accomplished through the returned set.</p>
    
    <p>It is imperative that the user manually synchronize on the returned set when iterating over it:</p>
    
    <p>Set s = Collections.synchronizedSet(new HashSet());<br>
          ...<br>
       <code>synchronized (s) {
          Iterator i = s.iterator(); // Must be in the synchronized block
          while (i.hasNext())
              foo(i.next());
    }</code>  </p>
    
    <p>Failure to follow this advice may result in non-deterministic behavior. </p>
  </blockquote>
  
  <p><strong>However</strong>, this does not apply to <code>Set.forEach</code>, which inherits the default method <code>forEach</code> from <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html#forEach-java.util.function.Consumer-">Iterable.forEach</a>.</p>
  
  <p>Now I looked into the source code, and here we can see that we have the following structure:</p>
  
  <ol>
  <li>We ask for a <code>Collections.synchronizedSet()</code>.</li>
  <li><p>We get one:</p>
  
  <pre><code>public static &lt;T&gt; Set&lt;T&gt; synchronizedSet(Set&lt;T&gt; s) {
      return new SynchronizedSet&lt;&gt;(s);
  }
  
  ...
  
  static class SynchronizedSet&lt;E&gt;
        extends SynchronizedCollection&lt;E&gt;
        implements Set&lt;E&gt; {
      private static final long serialVersionUID = 487447009682186044L;
  
      SynchronizedSet(Set&lt;E&gt; s) {
          super(s);
      }
      SynchronizedSet(Set&lt;E&gt; s, Object mutex) {
          super(s, mutex);
      }
  
      public boolean equals(Object o) {
          if (this == o)
              return true;
          synchronized (mutex) {return c.equals(o);}
      }
      public int hashCode() {
          synchronized (mutex) {return c.hashCode();}
      }
  }
  </code></pre></li>
  <li><p>It extends <code>SynchronizedCollection</code>, which has the following <em>interesting</em> methods next to the obvious ones:</p>
  
  <pre><code>// Override default methods in Collection
  @Override
  public void forEach(Consumer&lt;? super E&gt; consumer) {
      synchronized (mutex) {c.forEach(consumer);}
  }
  @Override
  public boolean removeIf(Predicate&lt;? super E&gt; filter) {
      synchronized (mutex) {return c.removeIf(filter);}
  }
  @Override
  public Spliterator&lt;E&gt; spliterator() {
      return c.spliterator(); // Must be manually synched by user!
  }
  @Override
  public Stream&lt;E&gt; stream() {
      return c.stream(); // Must be manually synched by user!
  }
  @Override
  public Stream&lt;E&gt; parallelStream() {
      return c.parallelStream(); // Must be manually synched by user!
  }
  </code></pre></li>
  </ol>
  
  <p>The <code>mutex</code> used here is the same object as to which <em>all</em> operations of <code>Collections.synchronizedSet</code> lock to.</p>
  
  <p>Now we can, judging by the <em>implementation</em> say that it is thread safe to use <code>Collections.synchronizedSet(...).forEach(...)</code>, but is it also thread safe <em>by specification</em>?</p>
  
  <p>(Confusingly enough, <code>Collections.synchronizedSet(...).stream().forEach(...)</code> is <em>not</em> thread safe by implementation, and the verdict of the specification seems to be unknown aswell.)</p>