我对多处理器机器中posix线程的并发性有一些疑问。我在SO中发现了类似的问题,但没有找到确凿的答案。
以下是我的理解。我想知道我是否正确。
Posix线程是用户级线程,内核不知道它。
内核调度程序会将Process(及其所有线程)视为一个调度实体。它是线程库,它反过来选择运行哪个线程。它可以在可运行的线程中分割内核给出的CPU时间。
用户线程可以在不同的cpu核心上运行。即让线程T1& T2由进程(T)创建,然后T1可以在Cpu1中运行,T2可以在Cpu2中运行但是它们不能同时运行。
如果我的理解正确,请告诉我。
...谢谢
答案 0 :(得分:9)
由于您使用“Linux”标记标记了您的问题,我将根据linux下的标准pthreads实现来回答它。如果您正在讨论"green" threads,它们是在VM /语言级别而不是操作系统上安排的,那么您的答案大多是正确的。但我在下面的评论是关于Linux pthreads的。
1)Posix线程是用户级线程,内核不知道它。
不,这肯定不正确。 Linux内核和pthreads库一起管理线程。内核执行上下文切换,调度,内存管理,缓存内存管理等。当然在用户级别完成了其他管理,但没有内核,pthreads的大部分功能都将丢失。
2)内核调度程序将Process(及其所有线程)视为一个调度实体。它是线程库,它反过来选择运行哪个线程。它可以在可运行的线程中分割内核给出的CPU时间。
不,内核将每个进程线程视为一个实体。它有自己的关于时间切片的规则,它考虑了进程(和进程优先级),但每个子进程线程都是一个可调度的实体。
3)用户线程可以在不同的cpu核心上运行。即让线程T1& T2由进程(T)创建,然后T1可以在Cpu1中运行,T2可以在Cpu2中运行但是它们不能同时运行。
没有。多线程程序需要并发执行。这就是同步和互斥体如此重要以及为什么程序员忍受多线程编程的复杂性的原因。
向您证明这一点的一种方法是查看带有ps
选项的-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)
不同。
答案 1 :(得分:5)
POSIX没有指定如何将使用pthread_create
创建的线程安排到处理器核心上。这取决于实施。
但是,我希望在质量实现中有以下内容,这是当前版本的linux的情况:
即。所有3个编号的语句对于当前的linux实现都是错误的,但理论上对于另一个符合POSIX的实现也是如此。
答案 2 :(得分:0)
大多数POSIX实现使用操作系统支持来提供线程功能 - 它们包装管理线程所需的系统调用。因此,线程的行为重新。调度等取决于底层操作系统。
所以,在大多数现代操作系统上:
使用POSIX线程的进程与具有多个线程的任何其他进程没有区别。
内核调度程序调度线程,而不是进程。 “进程”通常被视为具有代码,内存管理,配额,审计和安全权限但不执行的更高级别构造。除非线程运行其代码,否则进程无法执行任何操作,这就是为什么在创建进程时,同时创建“主线程”,否则什么都不会运行。操作系统调度算法可以使用线程运行的进程作为参数之一来决定接下来要运行哪一组准备好的线程 - 将一个线程与同一进程中的一个线程交换成本更低 - 但它不必如此。
在可运行线程之间切换内核给出的CPU时间是OS计时器中断的副作用,因为有更多就绪线程比运行它们的内核更多。经常不得不诉诸的任何机器(呃! - 我讨厌这个术语),'时间切片'应该被认为是超负荷的,应该有更多的CPU或更少的工作。理想情况下,线程只有在被另一个线程或IO驱动程序发出信号时才会变为就绪状态,而不是因为OS定时器中断决定运行它而不是另一个仍然可以执行有用工作的线程。
他们可以同时运行。如果两个线程准备就绪并且有两个核心,则将线程分派到两个核心上。如果它们来自同一个过程并不重要。