我一直遵循多线程只能在多个处理器系统上实现的概念,在这个系统中,每个线程都有多个处理器,并且每个线程可以同时执行。在这种情况下没有调度,因为每个线程都有专用于它的独立资源。 但是我在某个地方读到了它,我也可以在单处理器系统上进行多线程处理。 这是对的吗?如果是,则单处理器和多处理器系统之间有什么区别?
答案 0 :(得分:49)
我在某个地方读到了它,我可以在单个上进行多线程处理 处理器系统。这是对的吗?如果是,那么什么是 单处理器和多处理器系统之间的区别?
是的,您可以在单处理器系统上进行多线程处理。
在多处理器系统中,多个线程在不同的核心上执行同时。 例如 - 如果有两个线程和两个核心,那么每个线程将在单个核心上运行。
在单处理器系统中,多个线程一个接一个地执行,或者等到一个线程完成或被操作系统抢占,这取决于线程优先级和操作系统策略。但是运行的线程给出了一个幻觉,它们相对于用户空间应用程序所需的应用程序响应时间同时运行。
时间比较(示例):
如果两个线程各执行10us,那么在2处理器系统上,净时间为10us
如果两个线程各执行10us,则在1处理器系统上,净时间为20us
答案 1 :(得分:40)
当然,它可以在单处理器系统上完成,事实上它更容易。它的运行方式与运行多个进程相同 - 内核,通过计时器中断或其他类似机制,暂停一个,保存其机器状态,并将其替换为之前保存的另一个状态 - 唯一的区别是两个同一进程的线程共享相同的虚拟内存空间,使任务切换更加高效。
多处理器系统上的多线程实际上要困难得多,因为你有从多个cpu / core同时访问内存的问题,以及由此产生的所有讨厌的内存同步问题。
答案 2 :(得分:7)
四核系统上可以有四个以上的活动线程。 是调度,除非你能保证进程不会尝试创建比处理器更多的线程。
是的,您可以在单核计算机上拥有多个线程。
单处理器系统和多处理器系统之间的区别在于多处理器系统确实可以一次做多件事。它可以一次做N个事情,其中N是处理器核心的数量。单处理器核心一次只能做一件事。正如WhozCraig在他的评论中所说,这是实际和感知并发之间的差异。
答案 3 :(得分:5)
这是一个非常简化的例子。它实际上是我正在构建的程序的原型。它是单线程中协作式多任务的实现。
main
只是将quit
标志设置为false,并填充一系列函数指针(任务),然后调用loop
。
loop
使用setjmp
设置非本地跳转的返回点(将函数跳转 out 返回执行中的先前位置)然后继续调用第一个任务(函数)。
每项任务都以yield()
结尾。也就是说,任务函数都不是return
。它们不仅不包含return;
语句(由于它们是void
函数(即程序),它们会很好),但即使它在那里它们也不会到达return
因为yield
会跳回到setjmp
调用,这次会在if
中向loop
语句产生1。由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;
}
此示例与单处理器多任务计算机系统之间的区别在于,真正的处理器支持在执行过程中中断任务并稍后从同一位置恢复任务。在将任务作为单个函数的C模拟中,这实际上是不可能的。但是,任务可以由一系列C函数组成,每个函数都向调度程序(函数指针数组,或者链接列表)产生。
答案 4 :(得分:3)
是的,你完全可以。 我们从合作多任务开始到多线程,因为有人总是搞砸了合作部分。 您计算机上的每个程序至少有一个线程。可能更多。并且CPU每秒只需几百万次就可以在所有那些线程之间进行切换。如果他们都没有做任何事情,它甚至可能会闲置一段时间。
多核系统只表示这些线程中的两个或多个可以在并行运行。
但是,这样做会减少很多。在单核计算机上使用多线程所能做的就是模拟多任务处理。
多任务处理足以阻止GUI线程因长时间运行而锁定。但是实现起来通常很复杂,除非你得到编译器或Langauge的帮助(比如C#async ... await)。 结果,许多GUI程序员只使用多线程和调用来伪造多任务处理。如果该代码在单核或多核上运行,则无法实现此目的。
最重要的是,多任务处理不适合CPU绑定操作。但95%的异步问题都不受CPU限制。它们是网络或磁盘绑定。 在单一计算机上,多线程也无助于CPU绑定的东西。如果你有两个线程都需要100%的CPU时间(相同的程序或不同的一个),但只有一个核心来运行它们,CPU将只需要在49%运行两者之间切换,并使用剩余的2%用于所有这些其他只做一点点的线程。
最后,只有极少数问题实际上可以是多线程的。只是尝试多线程Fibonacci序列(每对一个线程),而不是让它更慢,更多的内存要求和更复杂。
TL;博士; 您需要多线程和多核计算机来解决CPU限制问题。 大多数异步问题都不受CPU限制。多任务就足够了。而且即使在单个核心机器上,您也可以完全使用线程进行多任务处理。
答案 5 :(得分:0)
在单个处理器上的多线程进程中,处理器可以在线程之间切换执行资源,从而导致并发执行。并发表示正在执行多个线程,但是实际上线程并没有同时运行。线程之间的切换足够快,以至于线程似乎可以同时运行。
在共享内存多处理器环境中的同一多线程进程中,该进程中的每个线程可以在单独的处理器上同时运行,从而导致并行执行,这是真正的同时执行。当进程中的线程数小于或等于可用处理器数时,操作系统的线程支持系统将确保每个线程在不同的处理器上运行。例如,在使用四个线程编程并在具有两个双核处理器的系统上运行的矩阵乘法中,每个软件线程可以在四个处理器内核上同时运行以同时计算一行结果。