多处理器机器中posix线程的并发性

我对多处理器机器中posix线程的并发性有一些怀疑。 我在SO发现了类似的问题,但没有find确凿的答案。

以下是我的理解。 我想知道我是否正确。

  1. Posix线程是用户级线程,内核不知道它。

  2. 内核调度程序将把进程(及其所有线程)视为一个调度实体。 线程库依次select运行哪个线程。 它可以在可运行的线程中分割由内核给出的CPU时间。

  3. 用户线程可以在不同的CPU核心上运行。 即让线程T1和T2由Process(T)创build,那么T1可以在Cpu1中运行,而T2可以在Cpu2中运行,但是它们不能同时运行

请让我知道,如果我的理解是正确的。

谢谢…

Solutions Collecting From Web of "多处理器机器中posix线程的并发性"

既然你用“Linux”标记了你的问题,我将根据linux下的标准pthreads实现来回答它。 如果您正在讨论在VM /语言级别而不是操作系统上安排的“绿色”线程 ,那么您的答案大部分是正确的。 但是我下面的评论是关于Linux pthreads的。

1)Posix线程是用户级线程,内核不知道它。

不,这当然是不正确的。 Linux内核和pthreads库一起工作来管理线程。 内核做上下文切换,调度,内存管理,缓存管理等。当然还有其他的用户级别的管理,但是没有内核的话,pthreads的大部分功能就会丢失。

2)内核调度程序会将进程(及其所有线程)视为一个调度实体。 线程库依次选择运行哪个线程。 它可以在可运行的线程中分割由内核给出的CPU时间。

不,内核将每个进程线程视为一个实体。 它有它自己的关于时间分割的规则,考虑到进程(和进程优先级),但是每个子进程线程是一个可调度的实体。

3)用户线程可以运行在不同的CPU核心上。 即让线程T1和T2由Process(T)创建,那么T1可以在Cpu1中运行,而T2可以在Cpu2中运行,但是它们不能同时运行。

并行执行预计用于多线程程序。 这就是为什么同步和互斥体非常重要,为什么程序员忍受了多线程编程的复杂性。


一种证明这一点的方法是使用-L选项查看ps的输出以显示关联的线程。 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线程是否仍然这样做,但历史上,pthread使用clone(2)系统调用来创建另一个线程副本:

与fork(2)不同,这些调用允许子进程与调用进程共享部分执行上下文,如内存空间,文件描述符表和信号处理程序表。

这与另一个完整进程创建时使用的fork(2)不同。

POSIX不指定如何使用pthread_create创建的线程计划到处理器核心。 这取决于实施。

但是,我期望在质量实现中使用以下内容,而对于当前版本的Linux,情况就是如此:

  • 线程是完整的内核线程,由内核调度
  • 来自同一进程的线程可以在不同的处理器上同时运行

也就是说,所有3个编号的语句在当前的linux实现中都是错误的,但理论上对于符合POSIX的另一个实现也是如此。

大多数POSIX实现使用OS支持来提供线程功能 – 它们包装管理线程所需的系统调用。 因此,线程的行为。 调度等依赖于底层操作系统。

所以,在大多数现代操作系统:

  1. 带有POSIX线程的进程与其他任何具有多线程的进程没有什么不同。

  2. 内核调度程序调度线程,而不是进程。 “进程”通常被认为是具有代码,内存管理,配额,审计和安全权限的更高级别的构造,而不是执行。 一个进程除非一个线程运行它的代码,否则什么也不做,这就是为什么当一个进程被创建时,同时创建一个“主线程”,否则什么都不会运行。 操作系统调度算法可以使用线程运行的进程作为参数之一来决定下一个运行就绪线程的集合 – 将一个线程与同一进程中的一个线程交换出去会更便宜 – 但是不必这样做。

    在可运行线程之间切换内核给出的cpu时间是OS线程定时器中断的一个副作用,当有更多的就绪线程比运行它们的内核多。 任何经常不得不求助的机器(呃! – 我讨厌这个术语),'时间分割'应该被认为是超负荷的,应该有更多的CPU或更少的工作。 理想情况下,线程只能在被另一个线程或IO驱动程序发送信号时准备就绪,而不是因为OS定时器中断决定运行而不是另一个线程,而这个线程仍然可以做有用的工作。

  3. 他们只能同时运行。 如果两个线程已准备就绪,并且有两个内核,则线程将分派到两个内核中。 不管他们是否来自同一个进程,都不重要。