简体   繁体   English

Java NIO和异步服务器的多线程

[英]Java NIO and multithreading for asynchronous server

I've been trying to pair NIO with multithreaded read handling in order to make a scalable server. 我一直在尝试将NIO与多线程读取处理配对,以便构建可扩展的服务器。 I cannot use any frameworks such as Netty or MINA because of several low level client-server protocol details that would be too much effort to implement in either. 我不能使用任何框架,如Netty或MINA,因为有几个低级别的客户端 - 服务器协议细节,这些细节在两者中都要付出太多努力。 I was just examining my code and I realized there is a potential race condition in this snippet: 我只是检查我的代码,我意识到这个片段中存在潜在的竞争条件:

//executes in selector thread
public void runSelector() {
    //...
    Set<SelectionKey> keys = selector.selectedKeys();
    for (Iterator<SelectionKey> keyIter = keys.iterator(); keyIter.hasNext(); ) {
        final SelectionKey key = keyIter.next();
        keyIter.remove();
        if (key.isValid() && key.isReadable()) { //point A
            //maybe some other short calculations
            ((SocketChannel) key.channel()).read(buffer); //point B
            workerThreadPool.submit(new Runnable() { public void run() { processRead(key, buffer); } });
        }
    }
    //...
}

//executes in a worker thread
private void processRead(SelectionKey key, ByteBuffer buf) {
    //... somewhere
    key.cancel();
    //...
}

It is a highly improbable event, but it is entirely possible that in a worker thread, I call key.cancel() while the selector thread is between the two points I commented in the runSelector() method. 这是一个非常不可能发生的事件,但完全有可能在工作线程中,我调用key.cancel(),而选择器线程位于我在runSelector()方法中注释的两个点之间。 Keep in mind that this could be deployed on a high concurrency machine, and the CPU core that runs the selector thread could be bogged down. 请记住,这可以部署在高并发机器上,运行选择器线程的CPU核心可能会陷入困境。 Is it a valid concern that key.cancel() could be called in a worker thread in between key.isReadable() and channel.read() in the selector thread and cause a CancelledKeyException? 是否有效关注key.cancel()可以在选择器线程中的key.isReadable()和channel.read()之间的工作线程中调用,并导致CancelledKeyException? Should I have some kind of thread safe collection that stores all the keys that are to be canceled so that runSelector() can cancel all of them at the end of an iteration? 我是否应该使用某种线程安全集合来存储要取消的所有键,以便runSelector()可以在迭代结束时取消所有这些键? How do the more professional projects like Netty or MINA handle such a case? 如Netty或MINA这样的专业项目如何处理这种情况?

Lock the resource, 锁定资源,

synchronized(key) {
    ((SocketChannel) key.channel()).read(buffer); //point B
}

If this looks odd look at this Oracle tutorial on concurrency. 如果这看起来很奇怪,请查看这个关于并发性的Oracle教程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM