Websocket Servlet线程安全



我正在使用WebSocketServlet (tomcat),我有一些关于在没有竞争条件问题的情况下正确使用它的问题。

我有一个实例变量(所以非线程安全),将跟踪所有的websocket连接

HashMap<String,MyServers> myNonThreadSafeVariable = HashMap<String,MyServers>

这是HashMap将包含的内容(大致…)

private final class MyServers extends MessageInbound {
       final Set<MyClients> clients = new CopyOnWriteArraySet<MyClients>();
       private String serverName; 
      @Override
      protected void onOpen(WsOutbound outbound) {}
      @Override
      protected void onClose(WsOutbound outbound) {}
      @Override
      protected void onText(WsOutbound outbound) {}
}
private final class Clients extends MessageInbound {
       private int clientID; 

      @Override
      protected void onOpen(WsOutbound outbound) {}
      @Override
      protected void onClose(WsOutbound outbound) {}
      @Override
      protected void onText(WsOutbound outbound) {}
}

现在. .在我的servlet生命周期中,我正在循环通过 mynonthreadsafvariable ,然后可能也将循环通过 mynonthreadsafvariable。客户端,然后可能还修改或添加客户端服务器等…

例如,当服务器连接时,在他的onOpen中会有类似

的内容
myNonThreadSafeVariable.put(key,this);

或者当客户端在他的onOpen中连接时(不要担心这个)

server = myNonThreadSafeVariable,get(key);
sever.clients.add(this);

或者当我需要ping所有服务器的所有客户端时:

for (Entry<String, MyServers> entry : myNonThreadSafeVariable.entrySet()) {
   MyServers server = entry.getValue();
   server.sendMessage("ping||");
   for (MyClients member : entry.getValue().clients) {
      client.sendMessage("")
   }
}

所以如果我正确理解为mynonthreadsafevvariable是全局的,那么mynonthreadsafevvariable将是全局的。客户等。

所以我的问题是,在这种情况下,什么是避免竞争条件的好做法?

在访问mynonthreadsafevvariable和mynonthreadsafevvariable时使用互斥锁和同步。客户吗?或者我应该完全避免使用实例变量?但是怎么做呢?

谢谢!

你可以使用ReadWriteLock:你在写的时候阻塞读写器,在读的时候只阻塞写器:

private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();
...
writeLock.lock();
try
{
    myNonThreadSafeVariable.put(key,this);
}
finally
{
    writeLock.unlock();
}
...
writeLock.lock();
try
{
    server = myNonThreadSafeVariable,get(key);
    sever.clients.add(this);
}
finally
{
    writeLock.unlock();
}
...
readLock.lock();
try
{
    for (Entry<String, MyServers> entry : myNonThreadSafeVariable.entrySet())
    {
        MyServers server = entry.getValue();
        server.sendMessage("ping||");
        for (MyClients member : entry.getValue().clients)
        {
            client.sendMessage("")
        }
    }
}
finally
{
    readLock.unlock();
}

此外,如果您想避免读锁,您可以复制整个集合并扫描副本,允许在通知时更改原始集合

相关内容

  • 没有找到相关文章

最新更新