9 Replies Latest reply: Jan 19, 2010 3:50 PM by 843789 RSS

    making set iterator thread-safe?

    843789
      Please consider:
      Set set = new HashSet();
      ........... // put stuff in "set"
      for(Iterator it = set.iterator(); it.hasNext(); ) {
        // <------ danger?
        Object s = (Object) it.next();
        .......
      }
      The only way to make this thread-safe??:
      Set set = new HashSet();
      ...........
      synchronized(set) {
        for(Iterator it = set.iterator(); it.hasNext(); ) {
          Object s = (Object) it.next();
          ......
        }
      }
      A different thread could, in theory, empty "set" between "it.hasNext()" and "it.next()"?
      So the entire (possibly huge/time consuming) "for" loop must be completely synchronized?

      thanks.
        • 1. Re: making set iterator thread-safe?
          843789
          Is set a field or a local variable, in this scenario?
          • 2. Re: making set iterator thread-safe?
            DrClap
            Yes, that's correct. If you don't want anything else to monkey with the set while you're iterating over it, then obviously you have to lock everybody else out.

            However it's likely there's something in the java.util.concurrent package which will allow other users to monkey with the set in restricted ways while you're iterating over it. Have a look there.
            • 3. Re: making set iterator thread-safe?
              843789
              paulcw wrote:
              Is set a field or a local variable, in this scenario?
              please, consider it a publicly accessible instance object.
              • 4. Re: making set iterator thread-safe?
                843789
                DrClap wrote:
                Yes, that's correct. If you don't want anything else to monkey with the set while you're iterating over it, then obviously you have to lock everybody else out.
                what i was trying to explore was the one line of byte code between:
                (line A) it.hasNext()
                // <------- chance of the jvm swapping in a different thread and running its code that references to "set", and performs add/remove on "set" that effects the iterator
                (line B) it.next

                That chance has just got to be near 0. I mean, the lines are right next to each other in the same thread. And synchronizing might in theory hurt performance. So, just as a thought experiment, since the chance of a synchronization conflict might be near zero, and performance improvement might be significant, why not just not sync."line A" and "line B" are right next to each other. Any, I am sure good developers will always sync.

                Edited by: rdkh on Jan 19, 2010 6:41 PM
                • 5. Re: making set iterator thread-safe?
                  843789
                  If I'm not mistaken, you wouldn't just have to synchronize on set, all other code referring to set would have to synchronize on it.
                  Otherwise you could get a concurrent modification exception.


                  That chance has just got to be near 0. I mean, the lines are right next to each other in the same thread. And synchronizing might in theory hurt performance. So, just as a thought experiment, since the chance of a synchronization conflict might be near zero, and performance improvement might be significant, why not just not sync."line A" and "line B" are right next to each other. Any, I am sure good developers will always sync.
                  I don't get your point or why you think another thread couldn't, say, add to the set between iterations of the loop.
                  • 6. Re: making set iterator thread-safe?
                    DrClap
                    rdkh wrote:
                    That chance has just got to be near 0.
                    Well, sure, that might be true. So if you don't mind your code crashing one time in a million (which could be twice a day in some environments), then don't worry about it.
                    • 7. Re: making set iterator thread-safe?
                      3004
                      rdkh wrote:
                      DrClap wrote:
                      Yes, that's correct. If you don't want anything else to monkey with the set while you're iterating over it, then obviously you have to lock everybody else out.
                      what i was trying to explore was the one line of byte code between:
                      (line A) it.hasNext()
                      // <------- chance of the jvm swapping in a different thread and running its code that references to "set", and performs add/remove on "set" that effects the iterator
                      (line B) it.next

                      That chance has just got to be near 0. I mean, the lines are right next to each other in the same thread.
                      It can happen so you have to assume it will. Thread safety is not about playing the odds. When the scheduler decides to switch a thread out, it does so. No matter what, it will be between to steps that are right next to each other. The fact that they're also "logically" close is 100% irrelevant.

                      And of course, if it's a multicore or multi-CPU machine, you can get other threads coming in between those statements without this thread even being swapped out.
                      And synchronizing might in theory hurt performance
                      Being fast won't matter if you can't be sure it's right.

                      Edited by: jverd on Jan 19, 2010 11:43 AM
                      • 8. Re: making set iterator thread-safe?
                        3004
                        paulcw wrote:
                        If I'm not mistaken, you wouldn't just have to synchronize on set, all other code referring to set would have to synchronize on it.
                        Right. If multiple threads are accessing a collection, and one or more of those threads can modify the collection, then all access to it must be synchronized, and the entire iteration loop has to be synced as well.
                        • 9. Re: making set iterator thread-safe?
                          843789
                          Hello rdkh,

                          I think CopyOnWriteArraySet is what you are looking for; read the JavaDoc carefully.

                          With kind regards
                          Ben