Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6374944

DelayQueue.contains() throws ConcurrentModificationException

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 5.0
    • core-libs

      FULL PRODUCT VERSION :
      java version "1.5.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
      Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode, sharing)

      1.5.0-06 and 6.0_65

      ADDITIONAL OS VERSION INFORMATION :
      OS independent

      A DESCRIPTION OF THE PROBLEM :
      java.util.concurrent.DelayQueue contains(Object) throws ConcurrentModificationException when take() will remove object from queue.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      in one thread loop

      Delayed ti...
      DelayQueue tasks....
      if (!tasks.contains(ti))
      tasks.put(ti);

      In other thread loop:

       tasks.take()




      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Should not throw
      ACTUAL -
      Throws in my case:
      java.util.ConcurrentModificationException
      at java.util.PriorityQueue$Itr.checkForComodification(PriorityQueue.java:456)
      at java.util.PriorityQueue$Itr.next(PriorityQueue.java:412)
      at java.util.concurrent.DelayQueue$Itr.next(DelayQueue.java:393)
      at java.util.AbstractCollection.contains(AbstractCollection.java:101)


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.util.concurrent.*;
      class DelayQueueBugExpose
      {
      private static final class __TaskInfo implements Delayed
      {
      final long delay;
      long t;

      __TaskInfo(
      long delay,
      long t
      )
      {
      this.delay = delay;
      this.t=t;
      };

      public long getDelay(TimeUnit unit)
      {
      return unit.convert(
      delay-((System.currentTimeMillis()-t)&0x7FFFFFFFFFFFFFFFl),
      TimeUnit.MILLISECONDS
      );
      };

      public int compareTo(Delayed s)
      {
      long sd = s.getDelay(TimeUnit.MILLISECONDS);
      long d = getDelay(TimeUnit.MILLISECONDS);
      return
      sd==d ? 0 : d >sd ? 1 : -1;
      };
      };

      static DelayQueue tasks = new DelayQueue();

      public static void main(String [] args)
      {
      Thread t1 = new Thread(
      new Runnable()
      {
      public void run()
      {
      try{
      for(;;)
      {
      __TaskInfo i = new __TaskInfo(2000,System.currentTimeMillis());
      if (!tasks.contains(i)) tasks.put(i);
      }
      }catch(Exception ex)
      {
      ex.printStackTrace();
      System.exit(-1);
      };
      };
      }
      );

      Thread t2 = new Thread(
      new Runnable()
      {
      public void run()
      {
      for(;;)
      {
      5 try{
      System.out.println("taken:"+tasks.take());
      }catch(InterruptedException ex){};
      }
      };
      }
      );
      t1.start();
      t2.start();
      };
      };
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      The DelayQueue is built around AbstractCollection. AbstractCollection is not thread safe and built around Iterators.

      contains(Object) uses iterator to scan for objects. This means that bulk operation

        while (e.hasNext())
      if (o.equals(e.next()))

      it uses make it prone to ConcurrentModificationException.

      Solution:
        Override _all_ methods of Queue and Collection implemented in DelayQueue with proper locking like this:

        public boolean contains(Object o) {
              final ReentrantLock lock = this.lock;
              lock.lock();
              try {
                       return super.contains(o);
              } finally {
                  lock.unlock();
              }
          }

      I did verified that it helps by modyfing provided sources.

            martin Martin Buchholz
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: