并发编程的一些基本概念

提到并发编程,最基础的概念就是搞明白什么是进程和线程了,关于这两个概念,可以参考我之前写的文章:
什么是进程和线程

CPU 核心数和线程数的关系

多核心:也指单芯片多处理器( Chip Multiprocessors,简称 CMP),CMP 是由美国 斯坦福大学提出的,其思想是将大规模并行处理器中的 SMP(对称多处理器)集成 到同一芯片内,各个处理器并行执行不同的进程。这种依靠多个 CPU 同时并行地 运行程序是实现超高速计算的一个重要方向,称为并行处理。

多线程: Simultaneous Multithreading.简称 SMT.让同一个处理器上的多个线 程同步执行并共享处理器的执行资源。

核心数、线程数:目前主流 CPU 都是多核的。增加核心数目就是为了增加线 程数,因为操作系统是通过线程来执行任务的,一般情况下它们是 1:1 对应关系,也 就是说四核 CPU 一般拥有四个线程。但 Intel 引入超线程技术后,使核心数与线程 数形成 1:2 的关系。
在这里插入图片描述

CPU 时间片轮转机制

我们平时在开发的时候,感觉并没有受 cpu 核心数的限制,想启动线程就启动线程,哪怕是在单核CPU上,为什么?这是因为操作系统提供了一种CPU时间片轮转机制。

时间片轮转调度是一种最古老、最简单、最公平且使用最广的算法,又称RR调度。每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。

百度百科对CPU时间片轮转机制原理解释如下:

如果在时间片结束时进程还在运行,则 CPU 将被剥夺并分配给另一个进程。 如果进程在时间片结束前阻塞或结来,则 CPU 当即进行切换。调度程序所要做的 就是维护一张就绪进程列表,当进程用完它的时间片后,它被移到队列的末尾。

时间片轮转调度中唯一有趣的一点是时间片的长度。从一个进程切换到另一 个进程是需要定时间的,包括保存和装入寄存器值及内存映像,更新各种表格和队 列等。假如进程切( processwitch),有时称为上下文切换( context switch),需要 5ms, 再假设时间片设为 20ms,则在做完 20ms 有用的工作之后,CPU 将花费 5ms 来进行 进程切换。CPU 时间的 20%被浪费在了管理开销上了。

为了提高 CPU 效率,我们可以将时间片设为 5000ms。这时浪费的时间只有 0.1%。但考虑到在一个分时系统中,如果有 10 个交互用户几乎同时按下回车键, 将发生什么情况?假设所有其他进程都用足它们的时间片的话,最后一个不幸的 进程不得不等待 5s 才获得运行机会。多数用户无法忍受一条简短命令要 5 才能 做出响应,同样的问题在一台支持多道程序的个人计算机上也会发。

结论可以归结如下:时间片设得太短会导致过多的进程切换,降低了 CPU 效率:而设得太长又可能引起对短的交互请求的响应变差。将时间片设为 100ms 通常 是一个比较合理的折衷。

在 CPU 死机的情况下,其实大家不难发现当运行一个程序的时候把 CPU 给弄 到了 100%再不重启电脑的情况下,其实我们还是有机会把它kill掉的,我想也正是 因为这种机制的缘故。

澄清并行和并发

我们举个例子,如果有条高速公路A,上面并排有8条车道,那么最大的并行车辆就是8辆,此条高速公路A同时并排行走的车辆小于等于8辆的时候,车辆就可以并行运行。CPU也是这个原理,一个 CPU相当于一个高速公路A,核心数或者线程数就相当于并排可以通行的车道;而多个CPU就相当于并排有多条高速公路,而每个高速公路并排有多个车道。

当谈论并发的时候一定要加个单位时间,也就是说单位时间内并发量是多少? 离开了单位时间其实是没有意义的。

俗话说,一心不能二用,这对计算机也一样,原则上一个 CPU 只能分配给一个 进程,以便运行这个进程。我们通常使用的计算机中只有一个 CPU,也就是说只有 一颗心,要让它一心多用同时运行多个进程,就必须使用并发技术。实现并发技术相当复杂,最容易理解的是“时间片轮转进程调度算法”。

综合来说:

并发:指应用能够交替执行不同的任务,比如单 CPU 核心下执行多线程并非是 同时执行多个任务,如果你开两个线程执行,就是在你几乎不可能察觉到的速度不 断去切换这两个任务,已达到"同时执行效果",其实并不是的,只是计算机的速度太 快,我们无法察觉到而已。
并行:指应用能够同时执行不同的任务,例:吃饭的时候可以边吃饭边打电话, 这两件事情可以同时执行。

高并发编程的意义、好处和注意事项

由于多核多线程的 CPU 的诞生,多线程、高并发的编程越来越受重视和关注。 多线程可以给程序带来如下好处:

(1)充分利用 CPU 的资源
从上面的CPU 的介绍,可以看的出来,现在市面上没有CPU的内核不使用多线程并发机制的,特别是服务器还不止一个 CPU,如果还是使用单线程的技术做思路,明显就out了。因为程序的基本调度单元是线程,并且一个线程也只能在一个CPU的一个核的一个线程跑,如果你是个i3的CPU的话,最差也是双核心 4 线程的运算 能力:如果是一个线程的程序的话,那是要浪费 3/4 的 CPU 性能:如果设计一个多线 程的程序的话,那它就可以同时在多个 CPU 的多个核的多个线程上跑,可以充分地 利用 CPU,减少 CPU 的空闲时间,发挥它的运算能力,提高并发量。

就像我们平时坐地铁一样,很多人坐长线地铁的时候都在认真看书,而不是为 了坐地铁而坐地铁,到家了再去看书,这样你的时间就相当于有了两倍。这就是为 什么有些人时间很充裕,而有些人老是说没时间的一个原因,工作也是这样,有的 时候可以并发地去做几件事情,充分利用我们的时间,CPU 也是一样,也要充分利用。

(2)加快响应用户的时间
比如我们经常用的迅雷下载,都喜欢多开几个线程去下载,谁都不愿意用一个线程去下载,为什么呢?答案很简单,就是多个线程下载快啊。
我们在做程序开发的时候更应该如此,特别是我们做互联网项目,网页的响应时间若提升 1s,如果流量大的话,就能增加不少转换量。做过高性能 web 前端调优 的都知道,要将静态资源地址用两三个子域名去加载,为什么?因为每多一个子域 名,浏览器在加载你的页面的时候就会多开几个线程去加载你的页面资源,提升网 站的响应速度。多线程,高并发真的是无处不在。

(3)可以使你的代码模块化,异步化,简单化
例如我们实现电商系统,下订单和给用户发送短信、邮件就可以进行拆分, 将给用户发送短信、邮件这两个步骤独立为单独的模块,并交给其他线程去执行。 这样既增加了异步的操作,提升了系统性能,又使程序模块化,清晰化和简单化。

发布了19 篇原创文章 · 获赞 6 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/qiangzi1103/article/details/104480083