gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 06:38:53 24 4
gpt4 key购买 nike

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

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

我在这里添加了发送和接收代码 - 不是很优雅,但它似乎工作......;-) 如果你想知道,我认为“发送”中的 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com