此系列文章是参考《JAVA并发编程从入门到精通》一书写的一些读后笔记,其中也会结合一些资料进行扩展补充,写的不准确的地方还望广大同胞指出,大家一起学习,一起码奴。
进程和线程
我们在用电脑的时候,经常会并行的去做一些事情,比如我们一边打着LOL、一边放着放着音乐、可能还要和基友开一个语音群聊。这就是操作系统多任务的表现,无论是过去单核CPU还是如今多核CPU都支持多任务同时运行。对于操作系统来说,玩LOL就是一个LOL进程、用QQ音乐听歌就是一个QQ音乐的进程。
当然某个进程可以同时做多件事,比如我们在聊QQ,发送消息、语音通话、消息通知等等是可以同时进行的,那么进程要干这么多事情,就是需要同时运行多个子任务,这些子任务也就称为线程。
多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之间快速切换,让每个线程交替运行,看起来就像同时执行一样,当然真正地同时执行多线程需要多核CPU才可能实现。
进程的概念
进程是操作系统进行资源分配的最小单位,其中资源包括:CPU、内存空间、磁盘IO等,同一进程的多个线程共享该进程的全部系统资源,进程与进程是相互独立的。
进程可以分为系统进程与用户进程,用于完成操作系统各种功能的进程成为系统进程,由用户自行启动的进程成为用户进程。
线程的概念
线程是CPU调度的最小单位,必须依赖于进程存在,线程自己本身不拥有系统资源,只拥有一点在运行中不可少的资源(如程序计数器、寄存器、栈)
任何一个程序都必须要创建线程,比如JAVA中的main函数、Servlet、定时器等等。
进程与线程对比
进程 | 线程 | |
---|---|---|
定义 | 进程是程序运行的一个实体的运行过程,是系统进行资源分配和调度的一个独立单位 | 线程是进程的运行和执行的最小调度单位 |
活泼性 | 不活泼,只是线程的容器 | 活泼,随时可以创建和销毁 |
系统开销 | 创建、撤销、切换开销大,资源要重新分配和收回 | 相对于进程仅保存少量寄存器内容,开销小在进程的地址空间执行代码 |
拥有资产 | 资源拥有的基本单位 | 相对于进程来说基本上不拥有资源,但会占用CPU |
地址空间 | 系统赋予独立的内存地址空间 | 线程只由相关堆栈寄存器和线程控制表TCB组成,寄存器可被用来存储线程内的局部变量 |
调度 | 仅是资源分配的基本单位 | 独立调度、分派的基本单位 |
安全性 | 进程之间相对比较独立,彼此不会互相影响 | 线程共享同一个进程下面的资源,可以相互通信和互相影响 |
高并发编程
由于多核多线程的CPU的诞生,多线程、高并发的编程越来越受到关注,那么多线程可以带来哪些好处呢?
- 充分利用CPU资源:程序的基本调度单位是线程,并且一个线程也只能在一个CPU的一个核的一个线程跑。如果你是一个i3的CPU,至少也是双核心四线程的运算能力,如果你的程序是单线程,那么就是有3/4的CPU性能被浪费。所以多线程的程序,才可以尽可能充分的利用CPU多核心的特性,发挥它的能力,提高并发量
- 加快响应用户时间:比如我们使用迅雷下载,都喜欢多开几个线程去下载多个资源。
多线程、高并发要注意的问题:
- 线程之间的安全性:在同一个进程里的多线程是资源共享的,比如我们多线程操作同一个内存地址中的一个变量,那么我们就需要去考虑它的安全性,防止同时对其进行操作而造成问题。
- 线程之间的死循环:为了解决线程之间的安全性问题JAVA引入了锁机制,锁可以使某个东西同时只能有一个线程持有,但一不小心这也可能会造成死锁的问题,不同的线程都在等待哪些根本不可能释放的锁。比如:两个线程A和B,分别代表两位用餐的人,他们都必须要获得共享刀和共享叉的锁,假如A线程获得了刀,B线程获得了叉,那么线程A就是进入阻塞状态等待获得叉,而线程B则阻塞等待A所拥有的刀。
- 线程太多使服务器资源耗尽:线程不是创建越多越好,过多的创建线程会导致耗尽系统内存以及CPU的“过度切换”,造成系统不可用,所以多线程的程序需要合理的使用多线程,比如借助线程池这样的技术去做多线程。