关于Number of Concurrent Threads in CreateIoCompletionPort的选定答案,我对I / O完成端口文档中“runnable thread”的定义有疑问:
当与之关联的可运行线程的总数时 完成端口达到并发值,系统阻塞 执行与该完成相关联的任何后续线程 port,直到可运行线程数低于并发 值。
我理解由于发布完成数据包而从GetQueuedCompletionStatus()
唤醒的线程可能因其他原因而发现自己处于睡眠状态(即,它尚未完成其工作且尚未返回呼叫{ {1}},但是正在睡觉,因此 - 如果我理解正确 - 根据上面的定义不是 runnable 。
我特别想知道的是:假设上面的线程在处理中正在休眠,因为它产生了另一个线程并且正在等待另一个线程完成?
如果线程的子线程处于可运行状态,是否会被认为处于'runnable'状态? -
如果没有,似乎无法从与完成端口关联的线程生成工作线程,而不会冒其他线程将被唤醒的危险,这样运行线程的总数超过GetQueuedCompletionStatus()
。
例如 - 假设我有50个线程等待NumberOfConcurrentThreads
,并发线程数为5,同时发布20个完成数据包,触发非常长的任务,每次线程唤醒执行其中一个任务,它立即产生一个新线程来完成工作,并等待该线程完成长任务,然后再返回调用GetQueuedCompletionStatus()
。
在这个例子中,20个线程会被唤醒并产生20个并行工作的子线程,还是只有5个线程?
(注意:ADDENDUM:我在我的特定情况下使用Boost.Asio实现了一个工作线程池 - 它在内部利用了I / O完成端口 - 我的工作线程使用JNI调用Java;在内部,Java代码产生自己的工作线程 - 这就是我关心的问题。)
答案 0 :(得分:1)
寻找这类问题答案的地方总是" Windows Via C/C++ (PRO-Developer)"作者:Jeffrey Richter和Christophe Nasarre。
在我的副本的第327页上,它清楚地解释了I / O完成端口跟踪它从GetQueuedCompletionStatus()
(或等效的)调用中释放的线程的线程ID,并将这些线程计为"运行"只要他们不调用任何使他们处于等待状态的功能。
因此,在您的示例中,假设调用GetQueuedCompletionStatus()
的线程正在等待由JNI创建的线程,则该线程被视为"未运行"因此IOCP可以从GetQueuedCompletionStatus()
释放另一个线程到服务请求。如果你的所有线程最终都会调用JNI并创建另一个线程,那么我认为你的设计有问题,因为你基本上每个事件创建一个"线程"可能无法扩展的设计以及不会创建外部线程的IOCP设计...
它是JNI层的一个函数,它产生了线程,还是纯粹是你正在调用的Java代码?如果后来我建议尽可能重新设计java代码......