java - 不必要的 Java 上下文切换

标签 java multithreading context-switching

我有一个 Java 线程网络(基于流的编程),通过固定容量 channel 进行通信 - 在 WindowsXP 下运行。根据我们对“绿色”线程(非抢占式)的经验,我们期望的是,如果 channel 变大,线程切换上下文的频率会降低(从而减少 CPU 时间)。然而,我们发现增加 channel 大小不会对运行时间产生任何影响。似乎发生的情况是,即使 channel 未满或空(即即使线程不必挂起),Java 仍决定切换线程,这会消耗 CPU 时间,但没有明显的优势。此外,更改线程优先级不会产生任何明显的差异。

我的问题是是否有某种方法可以说服Java不要进行不必要的上下文切换,而是推迟切换直到确实需要切换线程 - 有没有某种方法可以改变Java的调度逻辑?还是它对我没有注意到的事情做出了 react ?或者是否还有其他异步机制,例如线程工厂、可运行对象,甚至可能是守护进程(!)。答案似乎并不明显,因为到目前为止,我的通讯员还没有给出答案(包括最近的两位计算机科学教授)。或者也许我遗漏了一些非常明显的东西,人们无法想象我不知道它......

我在这里添加了发送和接收代码 - 不是很优雅,但它似乎可以工作......;-)如果您想知道,我认为“发送”中的 goLock 逻辑可能会导致问题,但暂时删除它并没有什么区别。我已经添加了发送和接收的代码...

<p>public synchronized Packet receive() {</p> <pre><code>if (isDrained()) { return null; } while (isEmpty()) { try { wait(); } catch (InterruptedException e) { close(); return null; } if (isDrained()) { return null; } } if (isDrained()) { return null; } if (isFull()) { notifyAll(); // notify other components waiting to send } Packet packet = array[receivePtr]; array[receivePtr] = null; receivePtr = (receivePtr + 1) % array.length; //notifyAll(); // only needed if it was full usedSlots--; packet.setOwner(receiver); if (null == packet.getContent()) { traceFuncs("Received null packet"); } else { traceFuncs("Received: " + packet.toString()); } return packet; </code></pre> <p>}</p> <p>synchronized boolean send(final Packet packet, final OutputPort op) {</p> <pre><code>sender = op.sender; if (isClosed()) { return false; } while (isFull()) { try { wait(); } catch (InterruptedException e) { indicateOneSenderClosed(); return false; } sender = op.sender; } if (isClosed()) { return false; } try { receiver.goLock.lockInterruptibly(); } catch (InterruptedException ex) { return false; } try { packet.clearOwner(); array[sendPtr] = packet; sendPtr = (sendPtr + 1) % array.length; usedSlots++; // move this to here if (receiver.getStatus() == StatusValues.DORMANT || receiver.getStatus() == StatusValues.NOT_STARTED) { receiver.activate(); // start or wake up if necessary } else { notifyAll(); // notify receiver // other components waiting to send to this connection may also get // notified, // but this is handled by while statement } sender = null; Component.network.active = true; } finally { receiver.goLock.unlock(); } return true; </code></pre> <p>}</p>


感谢您的提问!我一直在 Sun 论坛上讨论同样的问题,这是我在该论坛上的最后一篇文章:

Our best guess right now is that this effect results from Windows' scheduling logic.

Microsoft seems to be acknowledging that this area needs some improvement as it is introducing UMS - I quote: "UMS is recommended for applications with high performance requirements that need to efficiently run many threads concurrently on multiprocessor or multicore systems. ... UMS is available starting with 64-bit versions of Windows 7 and Windows Server 2008 R2. This feature is not available on 32-bit versions of Windows." Hopefully, Java will take advantage of UMS in some later release.

感谢您的帮助!

最佳答案

绿色线程消失了(也许 Solaris 仍然支持它,但我对此表示怀疑)。此外,Java 不会切换线程,而是操作系统会切换线程。 Java 所做的唯一一件事就是通过使用操作系统函数向操作系统发出线程处于空闲/等待/阻塞状态的信号。因此,如果您的程序遇到任何同步点,即 Thread.wait/sleep,它会发出信号,表明它不再需要 cpu。

除此之外,操作系统会维护时间片,并会从线程中夺走 cpu,即使这样,当其他线程等待 cpu 时,它仍然可以运行。

您可以在这里发布更多代码吗?

关于java - 不必要的 Java 上下文切换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1759135/

相关文章:

java - 从多个 portlet 访问 Util jar 中的 FacesContext

java - 从 IP 网络摄像头获取流

linux - Linux 内核中的上下文切换时间

java - 将 lombok 与 gradle 和 spring-boot 一起使用

java - 在 java maven 测试之前运行 python 脚本

java - 我应该使用终结器来解锁或释放任何线程锁或其他资源吗?

java - 连接被拒绝 - Java 客户端/服务器

正确关闭工作窃取线程池

java - 当线程改变状态时会发生上下文切换吗?

c - 为什么此代码与单个 printf 的行为不同? ucontext.h