大家好,我是小风哥。问:如果一个和尚挑水喝,两个和尚挑水喝,三个和尚没有水喝,大家一起捡柴火会不会很大?多线程一定会提高程序性能吗?在计算机科学中,这个问题的标准答案是“视情况而定”。计算机中的一切都是为了更高效地利用硬件资源而设计的,包括:CPU、内存、IO等,下面我们逐一了解一下。多线程和CPU多线程和CPU是程序员最了解的。我们知道多线程的目的之一就是充分利用多核,但是这里有一个前提,就是你要处理的任务真的可以拆分成独立的子任务。比如你想对一个数组的所有元素求和,那么这个任务可以拆分成两个独立的子任务:任务A计算前半部分数组元素的和,任务B计算后半部分的和数组元素,然后任务A和任务B交给两个线程执行。如果是在多核系统中,这种多线程并行处理会显着提升程序性能,但是使用多线程充分利用多核带来的性能提升是有上限的.原因很简单。这就像盖房子。盖房子不是一个大项目或小项目。一个人也不是不可能完成,但是增加六七个人显然可以加快工程速度,但是增加成百上千的工人盖房子可能反而会减慢速度。毕竟资源是有限的(可用的工具等),人多了需要协调的时间也会增加。多线程也是如此。当线程数超过某个临界点时,操作系统就会变得不堪重负(频繁的调度和切换),我称之为三和尚断水现象。但是如果系统是单核的,那么这种任务拆分就没有作用了,因为无论你创建多少线程,真正工作的只有一个CPU。当然,也有可能我们根本无法拆分任务,比如计算斐波那契数列,如果你不能计算出f(n-1)和f(n-2)的解,那么你没有办法计算当前问题的解f(n)。两个拆分任务A和B具有前后端依赖关系。这时候,多线程就没有用了。另一种可能性是您的问题规模很小。如果数组有成百上千个元素,那么此时你使用多线程就没有多大意义了。这时候使用多线程带来的好处还不足以抵消多线程带来的性能开销。多线程和IO多线程就一定能提高程序的IO性能吗?答案显然是否定的。最简单的场景是您的程序需要从极慢的网络链接读取和写入数据。在这种情况下,一个线程可能足以处理它。创建多个线程可能会对程序性能产生负面影响。损害。同样的情况也会出现在磁盘上。一个线程可能已经填满了磁盘。这时候创建多个线程读写文件显然不能加快程序的处理速度。在服务器端,程序员也使用多线程来加速程序处理。在这里,一个典型的问题是阻塞网络IO会导致调用线程挂起并挂起。这时候最简单的方法就是创建多个线程,每个线程处理一个请求,但是随着请求数量的增加,会创建越来越多的线程。这时,三个和尚没有水喝的现象开始出现。IO多路复用技术可以很好的解决这个问题。.当然,如果你的场景是IO会阻塞处理线程,那么此时创建两个线程,一个负责处理数据,一个负责等待IO,那么这样显然会提高程序性能。多线程与内存其实内存和磁盘一样,也有读写带宽的上限,但是我们的程序一般不会达到内存读写带宽的上限,这不是瓶颈。瓶颈在于多线程共享的内存资源(数据)和多核系统的缓存一致性问题。一般来说,多线程共享资源通常需要互斥访问。但是,为了加快内存读写速度,现代处理器都有缓存系统(L1、L2、L3)。每个核心都有自己的缓存。这些缓存内存中的数据会被缓存起来,也就是说一条数据可能同时存在于内存和各个核的缓存中,这会带来一个经典的数据一致性问题:一个核修改了数据中的数据后缓存,需要同步到其他核,这就要求缓存系统中必须有一个可以保证一致性的协议,否则程序可能会读到错误(过时)的数据。但是,这种同步有性能损失。多个线程频繁操作同一个变量可能会导致处理器缓存系统在内核之间频繁同步。在极端情况下,多线程程序的性能甚至比单线程程序还要差。因此,如果数据不能在多个线程间共享,就不要共享。如果一定要共享,那就尽量控制在最小范围内,读写频率控制在最小。
