你可以认为线程切换,线程创建就绪后的执行都是由某种“系统中断”来触发的。
假设线程A正在被cpu a执行着,结果来了个时钟中断,噗通,cpu a去响应了, a发现还有更高优先级的线程B需要执行(或者别的线程切换策略认为应该切换去B),那么保存好A的上下文就切换去B了。
假设线程C正在被cpu c执行着,结果来了个时钟中断,噗通,cpu c去响应了, c发现还有更高优先级的线程A需要执行(或者别的线程切换策略认为应该切换去A),那么保存好C的上下文就切换去A了。
上面这个过程你瞅瞅,线程A就从cpu a跑去cpu c执行了。和你A里面执行什么代码几乎没有啥关系。
事实上,容易产生这样的线程在多核间切换的还有IO中断。如果你使用阻塞式IO,当前线程执行阻塞 IO操作时会主动让出cpu, 那么线程在cpu间切换的频率会比使用非阻塞会高的多,而且和上面的情况不同:IO中断响应会无视线程cpu亲和设置的(因为你这个线程就是需要立即响应和处理这个IO,不像线程间切换是可以有机会等设置了亲和的那个核,来响应另外的时间中断实现该线程的唤醒的)!
拙文 线程抢占执行的有栈协程?有阻塞系统调用导致的多核间切换的历史重演! 有一些相关的更深入的讨论。
关于这方面的东西,建议你先学习一下操作系统相关章节,有很详细的论述。网上也有很多资料。
多线程本质上是为了充分利用CPU资源而出现的。
简单来说,线程一定是运行在核心上的。硬件上的多核多线程核C++的多线程大致相当于逻辑概念和实体概念的区别。
CPU有个超线程的概念,是有对应实体的,是在一个核心同时运行两个物理线程。大致是有一个运算单元配合两套逻辑处理单元,寄存器等,有时候会出现某个线程仅需要其中一部分资源时,可以使两个线程并行执行。但是这个核心上的两个线程恰巧用到了只有一套的部分(比如某个处理单元),那么就得有一个等待。所以超线程大部分应用只能提供大概5-15%的性能提升,和任务相关。所以会有像2核2线程的i3,或者4核8线程的i7这种区别。主要还是靠核心,任务一定是运行在实际处理单元上的。
然后C++的多线程,这是一个逻辑概念,其实就是把一个任务拆成并行处理的多个任务,每个任务都是运行在物理实体上(可以认为是CPU核心,超线程的事情不要可以先去管他)。但是,并不是说你一个线程就要固定占用一个核心,因为程序是有时间序列的。这部分操作系统分时并行部分讲的很详细。大致就是由于某些原因(IO,时序,需要等待其他线程的结果或通知之类),不是所有线程在所有时间都在同时用到CPU核心资源,所以就会有操作空间。就像公交车,如果要求每人都要有座位(线程要用核心),如果有20个座位,10个站,并不意味着只能拉20个人,每一站可能会有人上上下下(操作系统CPU调度),一趟拉上百人是很平常的事情。但是,同一时刻每个座位只能有一个人,但是下一站就可能换人,这个就类似运行线程和CPU核心的关系,具体谁占用,由操作系统决定。但是这个调度时间非常短,印象中之前windows是每秒调度64次。
C++多线程编程,是你自己把任务拆分成独立运行的不同部分,通过一些技术对这些任务进行同步,使之互相协调运行并充分利用CPU资源的技术。OpenMP是自动并行化一个库,它会自动把任务分散到不同的CPU去执行,相当于自动多线程。
至于你的例子,理论上,合理安排资源的话是可以充分利用所有的计算资源的,所以你的设想是没有问题的。但是实际任务,粗略分为计算密集型和IO密集型,前者一般线程数和CPU超线程数相仿,后者会大大超过。具体原因你看过操作系统CPU并行部分就知道了。
但是你要注意的是,CPU利用率100%,和程序最高运行效率是有区别的,合理安排不同线程,才能即充分利用CPU资源,又提高效率。不恰当的比喻就是,你一个线程弄个空的while循环,它肯定能占满一个核心,但是程序效率并没有提升。
其实很多东西书上都有也很基础,所以,多看书吧,其实也花不了多少时间。
多谢邀请。
你的问题对于稍微学过一些操作系统知识的人而言都会显得十分简单,可能有点幼稚(原谅我用这个词语),但我没有一丝嘲讽的意思。无知才是人类具有追求意识的起源,很多人自认为懂的很多,但他们不一定有自己的想法。
其他答主的解释我还没来得及细看,大概归结起来可以这么说,计算资源是大家共享的,只要还有线程没有做完,而系统也还有空闲的资源,就可以拿来用。所以,一般是不用担心浪费这个问题的。
但你直觉上有这个困扰,这是个好的现象,你可以自己着手去想一些解决方案,然后跟现有的比较,说不定你会有些什么新的见解也不一定,计算机还是一门很新的科学,不要被已有的东西束缚住,在这个领域里,因为每个人都具有自己的生产资料——大脑,而且跟数学等学科不一样,你可以一边学习一边赚钱,所以每个人都可以做出一些独到的贡献。
比如这个问题上,反映的一个事实就是,如果我的线程少于计算核心/硬件线程数量怎么办?已有的系统这个时候是没有办法的,当然其中一个核心可能时候会不停的计算的,但其他的只能干瞪眼了。曾经有一段时间,AMD被Intel狠狠的蹂躏的时候,有传言说AMD提出了一种技术,可以在需要的时候把几个核心合并成一个大核心,从而提高单线程的运算速度。一些不知底细的拥趸们为此欢呼雀跃。这是为什么呢,多个核心打不过并在一起也还是打不过啊?原因就在于大多数程序,特别是当时的一些游戏程序还不能充分发挥多个核心的计算能力。
解决的办法当然很简单,就是增加线程数量,但这个时候就加大了软件开发的困难,就是你正在学习的那些东西。另外一个方面的问题是很多线程的话,可能只有一部分可以被执行而其他线程必须休息,这样相互轮流,在一些需要同时处理很多并发事务的场合,这是经常遇到的。继而带来的一些问题是,大量线程相互轮流执行机制本身带来了一些额外的开销;而且为了充分利用计算资源,在多核心系统下需要把比如一个本来是顺序执行的计算任务拿来分成可以并行的子任务,也需要考虑如何分解它同时最大化执行效率;随着核心越来越多,这些问题会变得严重起来。
对于计算资源利用的一个误解是,看着CPU的占用率很低觉得不可思议,觉得它没干活。这是因为CPU的计算速度远超人的想象,一个看起来很复杂的具有成千上万步的计算过程,对CPU来说可能只是几个ms的事情,而统计运算开销的周期可能是在秒级以上的,所以大部分时候CPU的占用率都是很低的,因为的确没有那么多事情给它做,大部分时间它都空闲在那里,等待着下一个任务被激发,这一般是一个外部事件,通过中断传递给CPU最终把整个系统的执行状态不断向前推进。
CPU 可以有超线程,但是总的来说还是这样处理的吧
首相我们了解下为什么需要用到4核,这是由于不能盲目的提高CPU的主频和带宽,这样会产生各种实际很难处理的问题,比如温度飙升等。举例来说我们需要一个16G Hz的CPU才能在规定的时间内完成我们的计算任务,但是这个很难实现,所以我们曲线救国,把它拆成4个4G Hz的CPU(不考虑额外开销)。
线程是CPU处理实际业务的实体,就是说一个CPU只能执行一个线程,需要执行其他线程就必须要把当前的线程“挂”起来,再去执行。
从上面分析我们可以在知道4个CPU至少需要4个线程,才能把CPU全部利用起来。如果“16G Hz CPU” 拆分成8个2G Hz的CPU,就需要8个线程,依次类推。
你要加强你你的程序的计算能力,就需要多创建几个线程把每个实际的物理CPU都利用起来,这个就是算法的分解和合并能力了。简单举个例子,我们有一个32核心的志强CPU,通过查询字典的方式暴力破解密码,可以直接创建32个线程,把字典拆成32个部分,每一个线程运算一个部分,并行化的计算。
从C++来说,同一个线程只会跑在同一个核心上,而多个线程一般来说(默认的)跑在多个核心上——编译器和操作系统会负责处理的事情
具体到你的例子,修改优先级和修改时间片是无法达到这个效果的。你需要做的是把你的计算部分做成并行的。单独一个线程是达不到你要的效果的。