2015-02-10 56 views
0

我遇到了一个问题,我有一个类在连接到服务器时得到实例化。同步数据输出流

我在课堂上遇到问题的方法看起来像这样:

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” 是的ReentrantLock,DOUT是DOUT =新的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; 
     } 
    } 
} 
+0

为什么你会有大量的线程发送数据到同一个套接字?注意你的接收代码应该单独捕获'EOFException',而不记录它:这是正常的。您还应该在'DataOutputStream'和套接字输出流之间添加'BufferedOutputStream'。 [否则'flush()'是多余的。] – EJP 2015-02-10 23:48:26

+0

客户端互相发送数据。可能在任何时候,例如,客户端A和客户端B都向客户端C发送数据。 – shparkison 2015-02-11 00:42:37

+0

实际上,现在我想到了。你是对的,输出流被绑定到套接字上,不知道为什么我在想这个!这实际上有帮助,并且可能是我弄乱了的地方。实际上,我为每个客户端运行两个线程,一个用于发送,另一个用于接收。接收线程可能需要转发消息,所以此时可能客户端A的发送和接收都尝试使用相同的输出流发送...... – shparkison 2015-02-11 00:54:15

回答

2

这有可能是你的电话到输出流的一个抛出一个异常,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(); 
    } 
} 
+2

附注:不需要“catch”块。抛出异常似乎是更合适的事情,因为调用者会想知道错误(即重试)。 – duckstep 2015-02-10 23:55:09

+0

@duckstep同意。我已经删除了“catch”块。它可能在这里被捕获用于记录目的,但它不是必需的。 – 2015-02-11 00:02:28

+0

谢谢,这很有帮助!将看看它是否有助于解决我的问题。 – shparkison 2015-02-11 00:52:12