JDK-6470111 : Deadlock in Exchanger
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.concurrent
  • Affected Version: 5.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2006-09-13
  • Updated: 2011-02-16
  • Resolved: 2007-01-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0u12 b01Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Windows XP Home Edition Ver 2002 Service Pack 2

A DESCRIPTION OF THE PROBLEM :
java.util.concurrent.exchanger . If many processes wants to exchange, that will occur deadlock.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.concurrent.*;
import java.util.*;
public class ExecutorsAndBarriers2 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        MyExecutor myExecutor = new MyExecutor();
        for(int i1=0;i1<1024;i1++)
            myExecutor.execute(new MyThreadExchanger());
        new Thread(){
            MyThreadExchanger m = new MyThreadExchanger();
            public void run(){
                while(true)
                {
                    try
                    {
                        System.out.println("L: " + m.getLiving());
                        System.out.println("E: " + m.getInExchange());
                        Thread.sleep(4000);
                    }
                    catch(InterruptedException e){System.out.println(e.getLocalizedMessage());}
                }
            }
        }.start();
    }

}


class MyExecutor implements Executor{
    private static ExecutorService exs = Executors.newFixedThreadPool(3);
    public void execute(Runnable r)
    {
        exs.submit(r);
    }
}

class ObjectToExchange
{
    private static int ID=0;
    private int myID;
    public ObjectToExchange(){
        myID=ID++;
    }
    public int getID(){
        return myID;
    }
}

class MyThreadExchanger implements Runnable{
    private static int ID=0;
    private static volatile int living=0;
    private int myID;
    private static volatile int inExchange=0;
    private static Exchanger<ObjectToExchange> exchanger = new Exchanger<ObjectToExchange>();
    private ObjectToExchange ob;
    public int getLiving()
    {
        return living;
    }
    public int getInExchange()
    {
        return inExchange;
    }
    public MyThreadExchanger(){
        myID=ID++;
        living++;
        ob=new ObjectToExchange();
    }
    public void run(){
        System.out.println(myID + " : START");
        try
        {
            ObjectToExchange tmp;
            inExchange++;
            tmp = exchanger.exchange(ob);/*Implementacja z java z deadlock-iem*/
            inExchange--;
            System.out.println("Watek : " + myID + " : wymienil " + ob.getID() + " na : " + tmp.getID());
            ob=tmp;
        }
        catch(InterruptedException ie){System.out.println(ie.getMessage());}
        System.out.println(myID + " : STOP " + --living);
    }
}
---------- END SOURCE ----------

Comments
EVALUATION Here's a more compact test case: import java.util.concurrent.*; import java.util.*; public class Bug3 { public static void main(String[] args) throws Throwable { final int n = 128; final CountDownLatch done = new CountDownLatch(n); final Exchanger<Object> exchanger = new Exchanger<Object>(); final ExecutorService es = Executors.newFixedThreadPool(3); for (int i = 0; i < n; i++) es.submit(new Runnable() { public void run() { try { exchanger.exchange(new Object(), 1L, TimeUnit.SECONDS); done.countDown(); } catch (Throwable e) { throw new Error(e); }}}); done.await(); es.shutdown(); } } This bug was fixed in jdk 6 build 51, apparently by the Exchanger rewrite for: 6264015: Performance improvement to Exchanger and SynchronousQueue I was under the mistaken impression that this was only for performance, not reliability. We need to decide whether to backport all of Exchanger, or to do a point fix.
13-09-2006