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