Websocket Servlet是线程安全的

时间:2013-06-16 12:42:30

标签: multithreading servlets thread-safety websocket

我正在玩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生命周期中,我循环遍历 myNonThreadSafeVariable ,然后也可能循环遍历 myNonThreadSafeVariable.clients ,然后也可能修改或添加客户服务器等...

例如,当服务器连接时,在他的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("")
   }
}

所以,如果我正确地认为myNonThreadSafeVariable是全局的,那么myNonThreadSafeVariable.clients等......

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

在访问以下myNonThreadSafeVariable和myNonThreadSafeVariable.clients时使用互斥并对它们进行同步?或者我应该避免使用实例变量?但是如何?

谢谢!

1 个答案:

答案 0 :(得分:0)

你可以使用 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();
}

此外,如果您想避免读取锁定,您可以复制整个集合并扫描副本,以便在通知时更改原始集合的可能性。