private static volatile AtomicInteger blockClientCount = new AtomicInteger(0);
private static Object lock = new Object();
private static Lock reentrantLock = new ReentrantLock();
private static Condition condition = reentrantLock.newCondition();    
@Override
public void run() {
    Random random = new Random(this.hashCode());
    while (true) {
        String request = random.nextInt(10) + "" + IOUtil.operators[random.nextInt(4)] + (random.nextInt(10) + 1);
        System.out.println(this.getName() + " send request:" + request);
        if (socketConnect()) {
            BufferedReader in = null;
            PrintWriter out = null;
            try {
                out = new PrintWriter(socket.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                blockClientCount.incrementAndGet();
                reentrantLock.lock();
                try {
                    while (blockClientCount.get() % IOUtil.CLIENNT_NUM != 0) {
                        /**
                         * TODO java.lang.IllegalMonitorStateException
                         */
                        condition.wait();
                    }
                    condition.signalAll();
                } finally {
                    reentrantLock.unlock();
                }
                // synchronized (lock) {
                // while (blockClientCount.get() % IOUtil.CLIENNT_NUM != 0)
                // {
                // lock.wait();
                // }
                // lock.notifyAll();
                // }
                out.println(request);
                String response = in.readLine();
                System.out.println(this.getName() + " accept response:" + response);
            } catch (final Exception e) {
                e.printStackTrace();
            } finally {
                IOUtil.close(in);
                IOUtil.close(out);
            }
        }
        try {
            sleep(1000);
        } catch (InterruptedException e) {
            System.out.println(this.getName() + " was interrupted and stop");
            IOUtil.close(socket);
            break;
        }
    }
}
the java.lang.IllegalMonitorStateException will happen when i use ReentrantLock to wait, but it works well when i use synchronized , i can'not explain it. The reason is that reentrantLock is unlock before condition.wait(),but i don't know why. if someone can help me,i have submit the code to https://github.com/shanhm1991/demo_io.git