searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

线程到底能不能利用多核?

2023-07-24 11:37:15
15
0

最近在讲解Python多线程过程中,遇到一个被人提过多次的问题:Python多线程到底有没有应用价值?

回答这个问题,需要区分应用的特点。如果该应用是IO密集型的,则多线程很有必要,而且的的确确能够提升应用的性能;如果该应用是计算密集型的,那么多线程就显得多余,甚至会拖慢效率。众所周知,Python解释器存在GIL,它的存在直接导致Python应用最多只能用到单核。单核时代,多线程编程也是很常见的编程方式。所以可以得出这样的结论:在IO密集型应用中,Python多线程有很大价值。

由此,我又想到到另外一个问题:Java多线程能不能利用多核?毕竟Python多线程只能利用单核是自身设计导致的,Java没有GIL的限制。

先给出结论,Java多线程可以利用多核(可以做实验进行验证)。如果应用线程数M小于或等于核数N(N可以大于物理CPU个数,因为超线程技术),那么Java多线程甚至可以进行并行运算,多个线程指令同时被计算机执行。

学习过计算机理论的人都知道,进程是资源分配的基本单元,线程是操作系统调度的基本单元。这句话作为一个结论,最初我始终体会不到它的奥义。通过解释多线程能否利用多核这个问题,我终于弄清了其中的意思。

在Linux2.6版本之后的版本,内核线程实现方式基本采用NPTL。NPTL是一个1*1的线程库,就是说当你使用pthread_create方法创建一个线程后,在内核里就相应创建了一个调度实体,在Linux里就是一个轻量级进程LWP,并且描述这个实体的数据结构仍然是task_struct。所以Linux操作系统的调度单位可以认为仍然是以进程为单位。如果认为LWP是一个线程,那么说Linux操作系统的调度单位是线程也没问题,毕竟Linux使用LWP模拟了线程。更详细的Linux进程介绍可以参考《深入理解Linux内核》。

线程也是一个实体,那么它在操作系统中又是以何种形式存在的或者说线程在内存中是怎么分布的?

从上图可知,无论主线程栈,还是其它线程栈都在同一进程内。线程本身基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈)。

如果在Linux系统中创建N个线程(轻量级进程LWP),内核会同时创建N个task_struct用来表示这N个线程,并且这N个线程都会继承进程的部分资源、共享进程的部分区域(共享的资源种类和数量由创建线程的参数决定)。新建的线程任务被当做进程看待并将被分配到某个CPU的runqueue队列,等待被调度执行。

Java线程在JDK1.2之前,基于”绿色线程“的用户线程实现,在1.2版本及以后,使用内核线程实现多线程功能。所以,像Java这种语言的多线程是能够在多核上并发执行的。

小结

根据以上的分析,可总结出以下结论:大部分现代Linux操作系统的多线程是能够利用多核进行并行(不是并发,如果多个任务被分配到同一个CPU,则这些任务是并发执行)运算的。

0条评论
0 / 1000
萌哥玛丽
1文章数
0粉丝数
萌哥玛丽
1 文章 | 0 粉丝
萌哥玛丽
1文章数
0粉丝数
萌哥玛丽
1 文章 | 0 粉丝
原创

线程到底能不能利用多核?

2023-07-24 11:37:15
15
0

最近在讲解Python多线程过程中,遇到一个被人提过多次的问题:Python多线程到底有没有应用价值?

回答这个问题,需要区分应用的特点。如果该应用是IO密集型的,则多线程很有必要,而且的的确确能够提升应用的性能;如果该应用是计算密集型的,那么多线程就显得多余,甚至会拖慢效率。众所周知,Python解释器存在GIL,它的存在直接导致Python应用最多只能用到单核。单核时代,多线程编程也是很常见的编程方式。所以可以得出这样的结论:在IO密集型应用中,Python多线程有很大价值。

由此,我又想到到另外一个问题:Java多线程能不能利用多核?毕竟Python多线程只能利用单核是自身设计导致的,Java没有GIL的限制。

先给出结论,Java多线程可以利用多核(可以做实验进行验证)。如果应用线程数M小于或等于核数N(N可以大于物理CPU个数,因为超线程技术),那么Java多线程甚至可以进行并行运算,多个线程指令同时被计算机执行。

学习过计算机理论的人都知道,进程是资源分配的基本单元,线程是操作系统调度的基本单元。这句话作为一个结论,最初我始终体会不到它的奥义。通过解释多线程能否利用多核这个问题,我终于弄清了其中的意思。

在Linux2.6版本之后的版本,内核线程实现方式基本采用NPTL。NPTL是一个1*1的线程库,就是说当你使用pthread_create方法创建一个线程后,在内核里就相应创建了一个调度实体,在Linux里就是一个轻量级进程LWP,并且描述这个实体的数据结构仍然是task_struct。所以Linux操作系统的调度单位可以认为仍然是以进程为单位。如果认为LWP是一个线程,那么说Linux操作系统的调度单位是线程也没问题,毕竟Linux使用LWP模拟了线程。更详细的Linux进程介绍可以参考《深入理解Linux内核》。

线程也是一个实体,那么它在操作系统中又是以何种形式存在的或者说线程在内存中是怎么分布的?

从上图可知,无论主线程栈,还是其它线程栈都在同一进程内。线程本身基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈)。

如果在Linux系统中创建N个线程(轻量级进程LWP),内核会同时创建N个task_struct用来表示这N个线程,并且这N个线程都会继承进程的部分资源、共享进程的部分区域(共享的资源种类和数量由创建线程的参数决定)。新建的线程任务被当做进程看待并将被分配到某个CPU的runqueue队列,等待被调度执行。

Java线程在JDK1.2之前,基于”绿色线程“的用户线程实现,在1.2版本及以后,使用内核线程实现多线程功能。所以,像Java这种语言的多线程是能够在多核上并发执行的。

小结

根据以上的分析,可总结出以下结论:大部分现代Linux操作系统的多线程是能够利用多核进行并行(不是并发,如果多个任务被分配到同一个CPU,则这些任务是并发执行)运算的。

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0