I got 2 functions. The first one discoverHosts() sends an request message to other computers. After this it goes to sleep with the await command. A separate threat calls the handleMessage() function when he receives a response. After he handles the response he uses notifyAll() to let discoderHosts() know that he has to check that all responses are received.

DiscoverHosts() does await when he calls the function. However when the separate threat calls handleMessage(), discoverHosts() doesn't awake when handleMessage calls the signalAll(). I checked while debuggig if signalAll() is called and this is the case. I have almost the same bit of code somewhere else in my project where it does work.

Do any of you guys know what I am overlooking?

private final Lock lock = new ReentrantLock();
private final Condition allReceived = lock.newCondition();

private void discoverHosts() throws Exception {
    lock.lock();
    externalNodes = new HashMap<String, NodeAddress>();
    Message msg = new Message(null, "REQUEST_IP");
    logger.debug("Broadcasting ip request, waiting responses");
    channel.send(msg);
    // TODO:Write a time-out
    while (channel.getView().size() - 1 != externalNodes.keySet().size()) {
        logger.debug("Channel: " + (channel.getView().size() - 1));
        logger.debug("Responses: "+ externalNodes.keySet().size());
        allReceived.await();
    }
    logger.debug("All answers received");
    lock.unlock();
}

protected void handleMessage(Message msg) {
    lock.lock();
    if (!((String) msg.getObject()).matches("IP_RESPONSE:[0-9.]*"))
        return;
    logger.debug("Received answer from " + msg.getObject());
    String ip = ((String) msg.getObject()).replaceAll("IP_RESPONSE:", "");
    // externalHostIps.add(ip);
    NodeAddress currentAddress = new NodeAddress(ip, msg.getSrc());
    externalNodes.put(ip, currentAddress);
    logger.debug("Signalling all threads");
    allReceived.signalAll();
    lock.unlock();
    logger.debug("Unlocked");
}

Logger output:

4372 [main] DEBUG com.conbit.webhackarena.monitor.monitor.Monitor@3b91eb  - Broadcasting ip request, waiting responses
4372 [main] DEBUG com.conbit.webhackarena.monitor.monitor.Monitor@3b91eb  - Channel: 1
4372 [main] DEBUG com.conbit.webhackarena.monitor.monitor.Monitor@3b91eb  - Responses: 0
4394 [Incoming-1,webhackarena,leendert-K53SV-53745] DEBUG com.conbit.webhackarena.monitor.monitor.Monitor@3b91eb  - Received answer from IP_RESPONSE:192.168.1.106
4396 [Incoming-1,webhackarena,leendert-K53SV-53745] DEBUG com.conbit.webhackarena.monitor.monitor.Monitor@3b91eb  - Signalling all threads
4397 [Incoming-1,webhackarena,leendert-K53SV-53745] DEBUG com.conbit.webhackarena.monitor.monitor.Monitor@3b91eb  - Unlocked
有帮助吗?

解决方案

I think your problem is this line

if (!((String) msg.getObject()).matches("IP_RESPONSE:[0-9.]*"))
    return;

Which means under some condition you acquire the lock and never release it.

Always use try...finally blocks with Lock to avoid this issue.

protected void handleMessage(Message msg) {
    lock.lock();
    try {
        if (!((String) msg.getObject()).matches("IP_RESPONSE:[0-9.]*"))
            return;
        logger.debug("Received answer from " + msg.getObject());
        String ip = ((String) msg.getObject()).replaceAll("IP_RESPONSE:", "");
        // externalHostIps.add(ip);
        NodeAddress currentAddress = new NodeAddress(ip, msg.getSrc());
        externalNodes.put(ip, currentAddress);
        logger.debug("Signalling all threads");
        allReceived.signalAll();
    } finally {
        lock.unlock();
    }
}

其他提示

However when the separate threat calls handleMessage(), discoverHosts() doesn't awake when handleMessage calls the signalAll()

I suspect that you have two different instances of the class in question and since the Condition allReceived is private final, they are not actually dealing with the same condition.

If you are trying to debug this (or use System.out.println debugging), be sure that your instance of the wrapping class is the same in both threads.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top