java - 同步数据输出流

标签 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();
}

其中 sendLock 是一个 ReentrantLockdout = new DataOutputStream(socket.getOutputStream());。这适用于有限数量的线程,但如果我有大量线程同时调用此方法,我就会陷入死锁,程序就会停止。

这里会发生死锁吗?这对我来说没有意义,因为我已经移除了所有其他锁以排除它们,而我只剩下这个了。无论如何,冲洗是否会导致东西挂起或其他什么?似乎在某个时候它永远不会释放锁,我不确定为什么。

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

作为引用,Receive端的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;
        }
    }
}

最佳答案

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

检查您的日志以查看其中一个线程是否抛出异常。在您的代码中,我将使用 try-catch-finally block 而不是抛出 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();
    }
}

关于java - 同步数据输出流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28443971/

相关文章:

java - 为什么 HashMap 快速失败只是因为它提供了一种迭代其键的方法?

java - 如何防止Camel swagger 2.16.2的枚举参数类型

java - RecyclerView fragment 不出现

C++11代替 `GetExitCodeThread`监控线程状态?

java - 最小化多线程环境中的 SecureRandom 性能问题?

java - Web 应用程序似乎启动了一个名为的线程,但未能停止它。这很可能造成内存泄漏

c++ - 多线程中的输出不明确

mysql - 在 MySQL 中锁定

svn - 如何锁定svn

c# - NET 3.5 中 Monitor.TryEnter 的替代方案