多线程可以在单处理器系统上实现吗?

Ays*_*yse 59 c windows winapi multithreading

我一直遵循多线程只能在多个处理器系统上实现的概念,在这个系统中,每个线程都有多个处理器,并且每个线程可以同时执行.在这种情况下没有调度,因为每个线程都有专用于它的独立资源.但我在某个地方读到它,我也可以在单处理器系统上进行多线程处理.这是对的吗?如果是,那么单处理器和多处理器系统之间有什么区别?

Bar*_*mar 58

我在某个地方读过它,我也可以在单处理器系统上进行多线程处理.这是对的吗?如果是,那么单处理器和多处理器系统之间有什么区别?

是的,您可以在单处理器系统上执行多线程处理.

在多处理器系统中,多个线程同时在不同的核上执行.例如 - 如果有两个线程和两个核心,那么每个线程将在单个核心上运行.

在单处理器系统中,多个线程一个接一个地执行,或者等待一个线程完成或被操作系统抢占,具体取决于线程优先级和操作系统策略.但是运行的线程给出了它们同时运行的错觉,相对于用户空间应用程序所需的应用程序响应时间.

时间比较(示例):

如果两个线程各执行10us,则在2处理器系统上,净时间为10us

如果两个线程各执行10us,那么在1处理器系统上,净时间为20us

  • Chrome在*processes*中运行标签,而非线程.线程提高稳定性的说法是错误的.一个线程不可能崩溃并使其余线程继续运行.由于进程的所有线程共享一个公共地址空间,因此它们都可能受到任何一个线程破坏内存的影响.此外,由线程"崩溃"引起的非自愿终止会终止整个过程,而不仅仅是单个线程. (9认同)
  • 我认为BarathBushan的答案很简单,人们应该避免投票:( (4认同)
  • 很有帮助.谢谢 :) (2认同)
  • @R .. 好的,我已经删除了有争议的部分......也许我还没有阅读足够的内容来备份和证明线程的稳定性...... (2认同)

R..*_*R.. 57

当然,它可以在单处理器系统上完成,事实上它更容易.它的运行方式与运行多个进程相同 - 内核,通过计时器中断或其他类似机制,暂停一个,保存其机器状态,并将其替换为之前保存的另一个状态 - 唯一的区别是两个同一进程的线程共享相同的虚拟内存空间,使任务切换更加高效.

多处理器系统上的多线程实际上要困难得多,因为你有从多个cpu/core同时访问内存的问题,以及由此产生的所有讨厌的内存同步问题.

  • 不,你必须误读,因为你所说的陈述绝对是错误的. (3认同)
  • ⁺¹为"定时器中断".整个互联网都没有提到交换机在硬件中是如何完成的; 我以为它是某种计时器,但即使维基百科也是沉默的. (2认同)

Jim*_*hel 7

四核系统上可以有四个以上的活动线程.还有就是调度,除非你能保证进程不会尝试创建多个线程比有处理器.

是的,您可以在单核计算机上拥有多个线程.

单处理器系统和多处理器系统之间的区别在于多处理器系统确实可以一次做多件事.它可以一次做N个事情,其中​​N是处理器核心的数量.单处理器核心一次只能做一件事.正如WhozCraig在他的评论中所说,这是实际和感知并发之间的差异.


lus*_*oog 5

这是一个非常简单的例子.它实际上是我正在构建的程序的原型.它是单线程中协作式多任务的实现.

main只需将quit标志设置为false,并填充函数指针数组(任务),然后调用loop.

loop使用setjmp来设置非本地跳转(跳转返回点在执行功能的恢复到以前的位置),然后继续调用第一个任务(功能).

每项任务都以yield().也就是说,实际上没有任务功能return.它们不仅不包含一个return;语句(由于它们是void函数,即程序),它们会很好,但它们不会达到,return即使它在那里因为yield跳回到setjmp调用,这次对if语句产生1 在loop.语句控制的if语句在重新进入while循环之前选择不同的任务.

因此,每个任务函数都会运行多次,从而产生调度程序(if(setjmp...语句),该调度程序选择要运行的新任务.

#include <stdio.h> 
#include <setjmp.h> 

jmp_buf dispatch; 
int ntasks; 
void (*task[10])(void); 
int quit; 

void yield(void) { 
    longjmp(dispatch, 1); 
} 

void loop() { 
    static int i = 0; 
    if(setjmp(dispatch)) 
        i = (i+1) % ntasks; 
    while(!quit) 
        task[i](); 
} 

int acc = 0; 

void a(void) { 
    if (acc > 10) quit = 1; 
    printf("A\n"); 
    yield(); 
} 
void b(void) { 
    acc *= 2; 
    printf("B\n"); 
    yield(); 
} 
void c(void) { 
    acc += 1; 
    printf("C\n"); 
    yield(); 
} 

int main() { 
    quit = 0; 
    ntasks = 3; 
    task[0] = a; 
    task[1] = b; 
    task[2] = c; 
    loop(); 
    return 0; 
} 
Run Code Online (Sandbox Code Playgroud)

此示例与单处理器多任务计算机系统之间的区别在于,真正的处理器支持在执行过程中中断任务并稍后从同一位置恢复任务.在将任务作为单个函数的C模拟中,这实际上是不可能的.但是,任务可以由一系列C函数组成,每个函数都向调度程序(函数指针数组,或者链接列表)产生.


Chr*_*her 5

是的,你完全可以。很久以前(Win 95?)我们从协作多任务到多线程,因为总是有人把协作部分搞砸了。您计算机上的每个程序都至少有一个线程。可能更多。并且 CPU 保持在所有这些线程之间每秒疯狂地切换几百万次。如果他们都无事可做,它甚至可能会闲置一段时间。

多核系统仅意味着其中两个或多个线程可能并行运行。

但是,这样做会让您少很多。在单核机器上使用多线程所能做的就是模拟多任务。

多任务足以防止 GUI 线程因长时间运行而锁定。然而,实现起来通常很复杂,除非您从编译器或语言(如 C# async...await)获得一些帮助。结果,许多 GUI 程序员只是使用多线程和调用来伪造多任务。如果该代码在单核或多核上运行,则无关紧要。

最重要的是,多任务不适合 CPU 密集型操作。但是 95% 的异步问题都不是 CPU 限制的。它们是网络或磁盘绑定。在单核计算机上,多线程也无助于处理 CPU 密集型的东西。如果你有两个线程都需要 100% 的 CPU 时间(相同的程序或不同的程序)但只有一个内核来运行它们,那么 CPU 将只需要在两者都以 49% 的速度运行之间切换,并将剩余的 2% 用于所有这些其他线程只做一点点。

最后只有很少的问题可以被多线程处理。只需尝试对斐波那契数列进行多线程(每对一个线程),而不会使其变慢、内存要求更高且更复杂。

tl;博士; 您需要多线程和多核计算机来解决 CPU 限制问题。大多数异步问题不受 CPU 限制。多任务处理就足够了。而且您可以使用线程完全多任务处理,即使在单核机器上也是如此。