同步数据输出流

时间:2015-02-10 23:37:52

标签: java multithreading locking

我遇到一个问题,我有一个类在连接到服务器时被实例化。

我在课堂上遇到麻烦的方法如下:

public void sendData(byte[] dataToSend) throws IOException {
    sendLock.lock();

    int dataLength = dataToSend.length;
    dout.writeInt(dataLength);
    dout.write(dataToSend, 0, dataLength);
    dout.flush();

    sendLock.unlock();
}

其中sendLockReentrantLockdout = new DataOutputStream(socket.getOutputStream());。这将适用于有限数量的线程,但如果我有大量线程同时调用此方法,我会遇到死锁,程序就会停止。

有没有理由在这里发生僵局?这对我来说没有意义,因为我已经删除了所有其他锁以排除它们,我就是这个。无论如何,冲洗可能导致事情挂起或什么?它似乎在某种程度上它永远不会释放锁定,我不知道为什么。

如果我删除了锁,我会收到套接字错误,因为一个线程可能会在另一个线程有机会写入之前更改dataLength等。但是死锁不再发生。

作为参考,接下来是接收端的run方法:

public void run() {

    while (socket != null) {
        try {
            int dataLength = din.readInt();
            byte[] data = new byte[dataLength];
            din.readFully(data, 0, dataLength);
            Event e = ef.getEvent(data);
            node.onEvent(e);    
        } catch (SocketException se) {
            System.out.println(se.getMessage());
            break;
        } catch (IOException ioe) {
            System.out.println(ioe.getMessage()) ;
            break;
        }
    }
}

1 个答案:

答案 0 :(得分:3)

您对输出流的一次调用可能会引发异常,并且永远不会调用sendLock.unlock()。所有其他线程将永远等待。

检查日志以查看其中一个线程是否抛出异常。在你的代码中,我将使用try-catch-finally块而不是抛出IOException。这保证了,即使发生了不好的事情,锁也会被释放,因此其他线程可以继续工作。

public void sendData(byte[] dataToSend) throws IOException {
    try {
        sendLock.lock();

        int dataLength = dataToSend.length;
        dout.writeInt(dataLength);
        dout.write(dataToSend, 0, dataLength);
        dout.flush();
    }
    finally {
         sendLock.unlock();
    }
}