在多线程应用中,
while (result->Status == Result::InProgress) Sleep(50);
//process results
优于
while (result->Status == Result::InProgress);
//process results
? 通过这个,我问第一种方法是否会在等待结果而不是不断旋转时对其他线程有礼貌?我正在等待的操作通常需要大约1-2秒,并且处于不同的线程。
答案 0 :(得分:2)
我建议使用信号量来代替轮询。如果您更喜欢主动等待,则睡眠是比不断评估循环条件更好的解决方案。
答案 1 :(得分:1)
是的,睡眠和变体放弃了处理器。其他线程可以接管。但是有更好的方法可以等待其他线程。
不要使用空循环。
答案 2 :(得分:1)
它更好,但不是很多。
只要result->Status
不是volatile
,就允许编译器减少
while(result->Status == Result::InProgress);
到
if(result->Status == Result::InProgress) for(;;) ;
因为条件在循环内没有改变。
调用外部(因此隐式volatile
)函数Sleep
会改变这一点,因为这可能会修改result
结构,除非编译器知道Sleep
永远不会修改数据。因此,根据编译器的不同,第二种实现不太可能进入无限循环。
也无法保证对result->Status
的访问是原子的。对于特定的内存布局和处理器体系结构,读取和写入此变量可能包含多个步骤,这意味着调度程序可能决定介入中间。
因为此时所有通信都是简单的是/否,并且接收线程也应该等待否定回复,最好的方法是使用操作系统提供的相应线程同步原语来实现此效果。这样做的好处是,当条件发生变化时,您的线程会立即被唤醒,并且在此期间它不使用CPU,因为操作系统知道您的线程正在等待什么。
在Windows上,使用CreateEvent
和co。使用事件对象进行通信;在Unix上,使用pthread_cond_t
对象。
答案 3 :(得分:1)
这也取决于您的操作系统调度策略。例如,Linux默认情况下具有CFS调度,并且可以将处理器公平地分配给所有任务。但是如果你把这个线程作为带有FIFO策略的实时线程,那么没有睡眠的代码将永远不会重新处理处理器,除非有更高优先级的线程,相同的优先级或更低的优先级永远不会被调度,直到你从循环中断开。如果您应用SCHED_RR,那么相同优先级和更高优先级的进程将被安排但不会更低。