同步列表永久锁定

时间:2017-12-16 05:56:54

标签: java multithreading thread-synchronization

我创建了一个带有ServerSocket的服务器,并且所做的任何连接都被放入Connection的列表中。该列表已同步(Collections.synchronizedList(new ArrayList<Connection>())),我可以正确访问它,例如:

synchronized(getConnections()) {
    Iterator<Connection> it = getConnections().iterator();
    while(it.hasNext()) {
        try {
            if(!it.next().keepAlive()) {
                it.remove();
            }
        }catch(Exception error) {
            ErrorLogger.error(error);
        }
    }
}

但它会随机锁定某个地方。一旦锁定,它将永远锁定。

我创建了一个日志系统,它在每个用于此列表的同步块之前和之后记录消息。 (COMPLETE表示它经过了synchronized块)。 Pastebin of the logs with descriptions

以下是我在日志中看到的ADDED部分的代码:

DebugFile.write("ADDED connection");
//This is used to dump empty connections
synchronized(getConnections()) {//Synchronized
    getConnections().add(mini);//Adding to List
    Iterator<Connection> it = getConnections().iterator();
    while(it.hasNext()) {
        Connection con = it.next();
        if(con.getSocket() == null || !con.getSocket().isConnected() ||
                (con.getBungeeServer().equals("Unknown") && System.currentTimeMillis() > con.getCreateTime()+30000)){
            System.out.println("[MoltresBungee] Connection disconnecting because they have not identified within 30 seconds.");
            con.stop(false);
            it.remove();//Removes expired sessions
        }
    }
    Bungee.instance.getLogger().info("MoltresBungee - Active connections: " + getConnections().size());
}
DebugFile.write("ADDED connection - COMPLETE");//Logs complete

以下是REMOVE ALL的代码:

DebugFile.write("REMOVE ALL : " + name);
synchronized(getConnections()) {
    Iterator<Connection> it = getConnections().iterator();
    while(it.hasNext()) {
        Connection con = it.next();
        if(con == null || con.getSocket() == null || con.getSocket().isClosed() || con.getBungeeServer().equals(name)){
            DebugFile.write("REMOVE ALL : " + name + " removing: " + con.getBungeeServer());
            if(con != null && con.getSocket() != null) {
                try{
                    con.getSocket().close();
                }catch(Exception e){ErrorLogger.error(e);}
            }
            it.remove();
        }
    }
}
DebugFile.write("REMOVE ALL : " + name + " - COMPLETE");

添加代码假设添加到此列表的连接,然后删除此列表中丢失连接或从未完成握手的任何项目。

删除所有代码是为了从列表中删除任何具有相同名称或已经关闭的内容。

我使用synchronized(getConnections())大约十多个地方就像上面那样。

如果需要,这里是getConnections()方法:

public synchronized List<Connection> getConnections(){
    return connections;
}

为什么会锁定,我该如何解决?

编辑: 此外,客户端尝试连接重试直到连接,并且似乎所有先前的尝试仍然存在,当服务器打开时。这是列表锁定的时候。

0 个答案:

没有答案