我一直遵循这样的概念,即多线程只能在多处理器系统上实现,其中每个线程分配多个处理器并且每个线程可以同时执行。在这种情况下没有调度,因为每个线程都有单独的资源都专用于它。但我最近在某处读到它,我也可以在单处理器系统上进行多线程处理。这是对的吗?如果是,那么单处理器和多处理器系统有什么区别?
6 回答
Of course it can be done on a single-processor system, and in fact it's much easier that way. It works the same way as running multiple processes -- the kernel, via a timer interrupt or other similar mechanism, suspends one, saving its machine state, and replacing that by the previously-saved state of another -- the only difference being that two threads of the same process share the same virtual memory space, making the task-switch much more efficient.
Multi-threading on multi-processor systems is actually much more difficult, since you have issues of simultaneous access to memory from multiple cpus/cores, and all the nasty memory synchronization issues that arise out of that.
我最近在某处读到它,我也可以在单处理器系统上进行多线程处理。这是对的吗?如果是,那么单处理器和多处理器系统有什么区别?
是的,您可以在单处理器系统上执行多线程。
在多处理器系统中,多个线程同时在不同的内核上执行。例如-如果有两个线程和两个核心,那么每个线程将在单独的核心上运行。
在单处理器系统中,多个线程一个接一个地执行或等待一个线程完成或被操作系统抢占,具体取决于线程优先级和操作系统策略。但是正在运行的线程给人一种它们同时运行的错觉,相对于用户空间应用程序所需的应用程序响应时间。
时间比较(示例):
如果两个线程每个执行需要 10us,那么在 2 处理器系统上,净时间为 10us
如果两个线程每个执行需要 10us,那么在 1 个处理器系统上,净时间需要 20us
You can have more than four active threads on a quad core system. There is scheduling, unless you can guarantee that processes won't try to create more threads than there are processors.
Yes, you can have multiple threads on a single-core computer.
The difference between single processor and multi-processor systems is that a multi-processor system can indeed do more than one thing at a time. It can do N things at a time, where N is the number of processor cores. A single-processor core can only do one thing at a time. As WhozCraig said in his comment, it's the difference between actual and perceived concurrency.
是的,你完全可以。很久以前(Win 95?)我们从协作多任务到多线程,因为总是有人搞砸了协作部分。您计算机上的每个程序都至少有一个线程。可能更多。CPU 会在所有这些线程之间不停地切换,每秒几百万次。如果他们都无事可做,它甚至可能会闲置一段时间。
多核系统仅意味着这些线程中的两个或更多可能并行运行。
但是,这样做会给您带来的好处要少得多。在单核机器上使用多线程可以做的就是模拟多任务。
多任务处理足以防止 GUI 线程因为长时间运行的操作而锁定。但是,实现起来通常很复杂,除非您从编译器或语言(如 C# async...await)获得一些帮助。结果,许多 GUI 程序员只是使用多线程和调用来伪造多任务。如果该代码在单核或多核上运行,则与此无关。
最重要的是,多任务不适合 CPU 密集型操作。但是 95% 的异步问题都不受 CPU 限制。它们是网络或磁盘绑定的。在单核计算机上,多线程也无助于 CPU 绑定的东西。如果您有两个线程都需要 100% 的 CPU 时间(相同的程序或不同的程序)但只有一个内核来运行它们,那么 CPU 只需在两者都以 49% 的运行时间和剩余的 2% 运行之间切换其他只做一点点的线程。
最后,实际上只有极少数问题可以是多线程的。只需尝试对斐波那契数列(每对一个线程)进行多线程处理,而不会使其更慢、更需要内存和更复杂。
tl;博士; 您需要多线程和多核计算机来解决 CPU 绑定问题。大多数异步问题不受 CPU 限制。多任务处理就足够了。即使在单核机器上,您也可以使用线程完全执行多任务。
Here's a very simplified example. It's actually a prototype for a program I'm building. It's a implementation of cooperative multitasking in a single thread.
main
simply sets the quit
flag to false, and populates an array of function pointers (the tasks), and then calls loop
.
loop
uses setjmp
to set a return point for a non-local jump (a jump out of the function back to a previous location in the execution) and then proceeds to call the first task (function).
Each task ends with yield()
. That is, none of the task functions actually return
. Not only do they not contain a return;
statement (which would be fine since they are void
functions, ie. procedures), but they wouldn't reach the return
even if it was there because yield
jumps back to the setjmp
call, this time yielding a 1 to the if
statement in loop
. The statement controlled by the if
statement selects a different task before re-entering the while
loop.
So each task function runs multiple times, yielding to the dispatcher (the if(setjmp...
statement) which selects a new task to run.
#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;
}
The difference between this example and a single-processor multitasking computer system is the real processor supports interrupting a task in the middle of execution and resuming it later from the same spot. This isn't really possible in a C simulation with tasks as single functions. However, the tasks could be composed of a sequence of C functions which each yield to the dispatcher (an array of function pointers, maybe, or a linked-list).
在单个处理器上的多线程进程中,处理器可以在线程之间切换执行资源,从而实现并发执行。并发表示不止一个线程在进行,但这些线程实际上并没有同时运行。线程之间的切换发生得足够快,以至于线程可能看起来同时运行。
在共享内存多处理器环境下的同一个多线程进程中,进程中的每个线程都可以在单独的处理器上并发运行,从而产生并行执行,这才是真正的同时执行。当进程中的线程数小于或等于可用处理器数时,操作系统的线程支持系统确保每个线程运行在不同的处理器上。例如,在使用四个线程编程并在具有两个双核处理器的系统上运行的矩阵乘法中,每个软件线程可以同时在四个处理器内核上运行以同时计算一行结果。