为什么需要并发编程
- 加快响应用户的时间
我们在做程序开发的时候更应该如此,特别是我们做互联网项目,网页的响应 时间若提升 1s,如果流量大的话,就能增加不少转换量。做过高性能 web 前端调优 的都知道,要将静态资源地址用两三个子域名去加载,为什么?因为每多一个子域 名,浏览器在加载你的页面的时候就会多开几个线程去加载你的页面资源,提升网 站的响应速度。
- 使代码模块化、异步化、简单化
例如我们实现电商系统,下订单和给用户发送短信、邮件就可以进行拆分, 将给用户发送短信、邮件这两个步骤独立为单独的模块,并交给其他线程去执行。 这样既增加了异步的操作,提升了系统性能,又使程序模块化,清晰化和简单化。
- 充分利用CPU的资源
多核下如果还是使用单线程的技术做思路明显就 out 了,无法充分利用 CPU 的多核特点。如果设计一个多线程的程序的话,那它就可以同时在多个 CPU 的多 个核的多个线程上跑,可以充分地利用 CPU,减少 CPU 的空闲时间,发挥它的运算 能力,提高并发量。
理解进程和线程
进程是资源分配的基本单位。线程是资源调度的基本的单位。
进程
进程就可以视为程序的一个实例。大部分程序可以同时运行多个实例进程 (例如记事本、画图、浏览器 等),也有的程序只能启动一个实例进程(例如 网易云音乐、360 安全卫士等)。显然,程序是死的、静态的,进程是活的、动态 的。进程可以分为系统进程和用户进程。凡是用于完成操作系统的各种功能的进 程就是系统进程,它们就是处于运行状态下的操作系统本身,用户进程就是所有由 你启动的进程。站在操作系统的角度,进程是程序运行资源分配(以内存为主)的最小单位。
线程
线程必须依赖于进程而存在,线程是进程中的一个实体,是 CPU 调度和分 派的基本单位,它是比进程更小的、能独立运行的基本单位。线程自己基本上不 拥有系统资源,,只拥有在运行中必不可少的资源(如程序计数器,一组寄存器和栈), 但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。一个进程可 以拥有多个线程,一个线程必须有一个父进程。线程,有时也被称为轻量级进程 (Lightweight Process,LWP),早期 Linux 的线程实现几乎就是复用的进程,后来 才独立出自己的 API。
进程之间的通信
CPU核心数与线程数之间的关系
主流CPU都是多核的,线程是CPU调度的基本单位,同一时刻,一个CPU核心只能运行一个线程
前面说过,目前主流 CPU 都是多核的,线程是 CPU 调度的最小单位。同一 时刻,一个 CPU 核心只能运行一个线程,也就是 CPU 内核和同时运行的线程数 是 1:1 的关系,也就是说 8 核 CPU 同时可以执行 8 个线程的代码。但 Intel 引入 超线程技术后,产生了逻辑处理器的概念,使核心数与线程数形成 1:2 的关系。 在我们前面的 Windows 任务管理器贴图就能看出来,内核数是 6 而逻辑处理器 数是 12。 在 Java 中提供了 Runtime.getRuntime().availableProcessors(),可以让我们获 取当前的 CPU 核心数,注意这个核心数指的是逻辑处理器数。 获得当前的 CPU 核心数在并发编程中很重要,并发编程下的性能优化往往 和 CPU 核心数密切相关。