既然您用“Linux”标签标记了您的问题,我将根据 linux 下的标准 pthreads 实现来回答它。如果您谈论的是在虚拟机/语言级别而不是操作系统上安排的“绿色”线程,那么您的答案大多是正确的。但我下面的评论是关于 Linux pthreads 的。
1) Posix 线程是用户级线程,内核不知道。
不,这肯定是不正确的。Linux 内核和 pthreads 库一起工作来管理线程。内核负责上下文切换、调度、内存管理、高速缓存管理等。当然还有其他的管理在用户级别完成,但是没有内核,pthread 的大部分功能都会丢失。
2)内核调度器将进程(及其所有线程)视为一个调度实体。依次选择运行哪个线程的是线程库。它可以在可运行的线程中分割内核给定的 cpu 时间。
不,内核将每个进程线程视为一个实体。它有自己的时间片规则,考虑了进程(和进程优先级),但每个子进程线程都是一个可调度的实体。
3) 用户线程可以在不同的 cpu 内核上运行。即让线程 T1 和 T2 由 Process(T) 创建,然后 T1 可以在 Cpu1 中运行,T2 可以在 Cpu2 中运行,但它们不能同时运行。
不会。多线程程序需要并发执行。这就是为什么同步和互斥锁如此重要,以及为什么程序员要忍受多线程编程的复杂性。
向您证明这一点的一种方法是查看ps
with-L
选项的输出以显示关联的线程。 ps
通常将多个线程进程包装在一行中,但-L
您可以看到内核为每个线程都有一个单独的虚拟进程 ID:
ps -ef | grep 20587
foo 20587 1 1 Apr09 ? 00:16:39 java -server -Xmx1536m ...
相对
ps -eLf | grep 20587
foo 20587 1 20587 0 641 Apr09 ? 00:00:00 java -server -Xmx1536m ...
foo 20587 1 20588 0 641 Apr09 ? 00:00:30 java -server -Xmx1536m ...
foo 20587 1 20589 0 641 Apr09 ? 00:00:03 java -server -Xmx1536m ...
...
我不确定 Linux 线程是否仍然这样做,但历史上 pthreads 使用clone(2)
系统调用来创建自身的另一个线程副本:
与 fork(2) 不同,这些调用允许子进程与调用进程共享其部分执行上下文,例如内存空间、文件描述符表和信号处理程序表。
fork(2)
这与创建另一个完整进程时使用的不同。