在我的代码中,我有一个循环,等待从不同的线程更改某个状态.另一个线程工作,但我的循环永远不会看到更改的值.它永远等待.但是,当我System.out.println
在循环中放置一个语句时,它突然起作用了!为什么?
以下是我的代码示例:
class MyHouse {
boolean pizzaArrived = false;
void eatPizza() {
while (pizzaArrived == false) {
//System.out.println("waiting");
}
System.out.println("That was delicious!");
}
void deliverPizza() {
pizzaArrived = true;
}
}
Run Code Online (Sandbox Code Playgroud)
while循环正在运行时,我deliverPizza()
从另一个线程调用来设置pizzaArrived
变量.但循环仅在我取消注释System.out.println("waiting");
语句时才有效.这是怎么回事?
请解释为什么忙碌等待通常不赞成,而旋转通常被认为是好的.据我所知,它们都无限循环,直到满足某些条件.
来自维基百科关于投票的文章
计算机科学中的轮询或轮询操作是指客户端程序将外部设备的状态作为同步活动进行主动采样.轮询最常用于输入/输出(I/O),也称为轮询I/O或软件驱动的I/O.
轮询有时与忙等待轮询(忙等待)同义.在这种情况下,当需要I/O操作时,计算机除了检查I/O设备的状态之外什么都不做,直到它准备就绪,此时访问设备.换句话说,计算机等待设备准备就绪.
轮询还指的是重复检查设备是否准备就绪的情况,如果不是,则计算机返回到不同的任务.尽管不像繁忙等待那样浪费CPU周期,但这通常不如轮询,中断驱动I/O的替代方案那样有效.
因此,当一个线程不使用"条件变量"时,它会被称为"轮询"数据更改还是"忙等待"?
是否有haskell库函数来监视文件而不进行轮询?
通过民意调查我会做这样的事情:
monitor file mtime handler = do
threadDelay n -- sleep `n` ns
t <- getModificationTime file
if t > mtime
then handler >> monitor file t handler
else monitor file mtime handler
Run Code Online (Sandbox Code Playgroud)
我想要的是一个阻塞的getModificationTime,它将被系统唤醒.有什么东西可用吗?
如果只有posix系统可用,我会非常高兴,但越便携越好:-)
编辑:我知道 hinotify,但我在Mac上(这就是为什么我提到POSIX).
我试图从分叉过程的STDOUT中读取.但是,如果我正在无限地从管道读取,for loop
即使没有数据通过管道也会忙着等待(如果我错了请纠正我),我想必须有更好的方法来做其他事情比使用sleep
,如果它是短的间隔,可能是回调,这我不知道.以下是我尝试过的代码片段.
pid_t pid = fork();
switch (pid) {
case 0:
dup2 (pipes[1], STDOUT_FILENO );
dup2(pipes[1], STDERR_FILENO);
close(pipes[0]);
close(pipes[1]);
execv(path, args);
break;
default :
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
child_pid = pid;
signal(SIGHUP, mysighandle);
close(pipes[1]);
ssize_t nbytes;
for (;;) {
nbytes = read(pipes[0], buf, BUFSIZE);
if (nbytes == -1){
break;
}
if (nbytes == 0) {
break;
}
syslog(LOG_NOTICE, "%s", buf);
Run Code Online (Sandbox Code Playgroud)
有人可以建议一个没有忙碌的更好的方法,可以用来从管道读取数据吗?由于我是初学者C
,所以对代码片段的任何引用都很受欢迎.
问候.
我有以下简单的代码:
package main;
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws InterruptedException {
new Main();
}
public Main() throws InterruptedException {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.schedule(new MyRunnable(), 10, TimeUnit.SECONDS);
System.out.println("Shutting down...");
executor.shutdown();
System.out.println("Awaiting termination...");
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES);
System.out.println("Main finished!");
}
private class MyRunnable implements Runnable {
public void run() {
System.out.println("Finished running!");
}
}
}
Run Code Online (Sandbox Code Playgroud)
实际上,虽然我的真实代码比这更复杂,但我可以在这些方面隔离问题.代码基本上等待10秒运行runnable,然后通知主程序的结束.
但是,我注意到了10秒钟,我的核心之一用于100%.
如果我评论这一行:
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES);
Run Code Online (Sandbox Code Playgroud)
cpu核心也以100%使用,主程序也在Runnable之前完成.
如果我评论这一行:
executor.shutdown();
Run Code Online (Sandbox Code Playgroud)
cpu已正确使用但程序无法完成.
如果我评论前两行,则cpu正确使用但主程序无法完成.
executor.shutdown();
做某种忙碌的等待而不是仅仅禁用提交新任务?附加细节:
$ java -version
java version "1.6.0_26" …
Run Code Online (Sandbox Code Playgroud) 我有一个MPI程序,它过度订阅/过度使用其处理器.那就是:进程多于处理器.
但是,在给定时间内,这些进程中只有少数是活动的,因此不应该争用计算资源.
但是,就像来自海底总动员的一群海鸥一样,当这些过程等待通信时,他们都在忙着循环,问"我的?我的?我的?"?
我正在使用英特尔MPI和OpenMPI(适用于不同的机器).我怎样才能说服他们既没有繁忙的循环?
我的快速而肮脏的解决方案是MPI_Iprobe
在带有sleep命令的循环中使用(参见此处).
#include <iostream>
#include <thread>
#include <mutex>
int main()
{
std::atomic<bool> ready = false;
std::thread threadB = std::thread([&]() {
while (!ready) {}
printf("Hello from B\n");
});
std::this_thread::sleep_for(std::chrono::seconds(1));
printf("Hello from A\n");
ready = true;
threadB.join();
printf("Hello again from A\n");
}
Run Code Online (Sandbox Code Playgroud)
这是 CppCon 演讲中的一个例子https://www.youtube.com/watch?v=F6Ipn7gCOsY&ab_channel=CppCon(17分钟)
目标是先打印Hello from A
然后允许threadB
开始。很明显,应该避免忙等待,因为它使用了大量的 CPU。
作者说while (!ready) {}
循环可以ready
由编译器优化(通过将 的值放入寄存器),因为编译器看到threadB
从不睡觉所以ready
永远不会改变。但是即使线程从不休眠,另一个线程仍然可以更改该值,对吗?没有数据竞争,因为它ready
是原子的。作者声明这个代码是UB。有人可以解释为什么允许编译器进行这样的优化吗?
我一直在为多媒体消息构建一个高吞吐量的服务器应用程序,实现语言是C++。每台服务器可以独立使用,也可以将多台服务器连接在一起,创建一个基于DHT的覆盖网络;服务器就像Skype一样的超级对等点。
工作正在进行中。目前,服务器每秒可以处理大约 200,000 条消息(256 字节消息),并且在我的机器(Intel i3 Mobile 2 GHz、Fedora Core 18(64 位)、4 GB RAM)上的最大吞吐量约为 256 MB/s长度为 4096 字节的消息。服务器有两个线程,一个线程用于处理所有 IO(基于 epoll,边缘触发),另一个线程用于处理传入的消息。覆盖管理还有另一个线程,但在当前的讨论中无关紧要。
讨论中的两个线程使用两个循环缓冲区共享数据。线程编号 1 使用一个循环缓冲区为线程编号 2 的新消息入队,而线程编号 2 通过另一个循环缓冲区返回已处理的消息。服务器是完全无锁的。我没有使用任何同步原语,甚至没有使用原子操作。
循环缓冲区永远不会溢出,因为消息是池化的(在启动时预先分配)。事实上,所有重要/经常使用的数据结构都被集中起来以减少内存碎片并提高缓存效率,因此我们知道服务器启动时我们将创建的最大消息数,因此我们可以预先计算最大缓冲区的大小,然后相应地初始化循环缓冲区。
现在我的问题是:线程 #1 将序列化消息一次一条消息(实际上是指向消息对象的指针)排入队列,而线程 #2 以块(32/64/128 的块)从队列中取出消息,然后返回通过第二个循环缓冲区以块的形式处理消息。如果没有新消息,线程#2 会一直忙着等待,因此让 CPU 核心之一一直忙着。我怎样才能进一步改进设计?忙等待策略的替代方案是什么?我想优雅而有效地做到这一点。我考虑过使用信号量,但我担心这不是最好的解决方案,原因很简单,每次我在线程 #1 中排队消息时都必须调用“sem_post”,这可能会大大降低吞吐量,第二个线程必须调用“sem_post”等于防止信号量溢出的次数。另外我担心信号量实现可能在内部使用互斥锁。
第二个不错的选择可能是使用信号,如果我能发现一种算法,仅当第二个线程“清空队列并且正在调用 sigwait”或“已经在等待 sigwait”,简而言之信号必须提高最少次数,尽管如果信号比需要的次数多几次也不会受到伤害。是的,我确实使用过谷歌搜索,但我在互联网上找到的解决方案都不是令人满意的。以下是一些注意事项:
A. 服务器在进行系统调用时必须浪费最少的 CPU 周期,并且必须使用最少的系统调用次数。
B. 必须有非常低的开销并且算法必须是高效的。
C. 没有任何锁定。
我希望所有选项都摆在桌面上。
这是我共享服务器信息的站点的链接,以便更好地了解其功能和目的:www.wanhive.com
在大学的课程中,我们学习Threads
并使用了“忙等待”方法作为Car
在TrafficLight
. 对于这个任务,我们构建了三个类:
TrafficLight (implements Runnable)
Car (implements Runnable)
Main
在我们的Main
班级中,我们开始了两个Thread
s,一个是Car
,一个是TrafficLight
。在Car
具有布尔属性hasToWait
。run()
此类中的方法的工作方式是,while
只要hasToWait == true
. 为了改变这一点,我们notifyCar()
在Car
类中有一个方法,它被TrafficLight
. 中的run()
方法TrafficLight
通过aThread.sleep()
来模拟一定的等待时间。
在我的教授那里一切正常,但最终我遇到了严重的问题。只要类中的while
循环Car
为空。当我把一个System.out.println()
-这是不是空的,它的工作原理。但如果Syso 为空,则结果是不显示方法的Text Run
。当Thread.sleep()
inTrafficLight
为0
. 比它适用于空while
循环。
这是我的代码:
package trafficlight;
public class Car implements Runnable …
Run Code Online (Sandbox Code Playgroud)