进程与线程相信是经常见到的两个名词,无论是在课本上看到,还是操作系统上看到,亦或是办公过程中处理问题都多多少少会遇到。那这俩东西怎么区分呢,又有着怎样的关联?今天一起来盘点盘点。
从表象上看,其实操作系统已经告诉我们进程(processor)的概念了,Windows系统当我们打开任务管理器时在列表里会有进程名称如“Chrome”、“Java”、“Intellij idea”等等,Linux系统执行个ps -ef或者top命令则可用把进程列表打开,同时可以看到每个进程占用的内存、CPU情况。而要看线程(thread)列表则不是那么的容易,在Linux下可以通过htop命令查看。
如下列出的进程列表
Processes: 684 total, 3 running, 681 sleeping, 3278 threads 23:43:36
Load Avg: 4.02, 4.32, 4.39 CPU usage: 3.12% user, 5.84% sys, 91.2% idle
SharedLibs: 466M resident, 56M data, 33M linkedit.
MemRegions: 245640 total, 5196M resident, 173M private, 1260M shared.
PhysMem: 16G used (2937M wired), 418M unused.
VM: 25T vsize, 3136M framework vsize, 90519394(0) swapins, 94810826(0) swapouts.
Networks: packets: 93868796/81G in, 58408386/32G out.
Disks: 41288557/806G read, 27863631/598G written.
PID COMMAND %CPU TIME #TH #WQ #PORTS MEM PURG CMPRS PGRP
59540 top 19.1 00:01.82 1/1 0 26 6620K+ 0B 0B 59540
0 kernel_task 15.4 47:02:41 173/8 0 0 1027M+ 0B 0B 0
80335 WindowServer 15.1 31:45:06 14 6 4436+ 887M- 17M+ 172M- 80335
99955 Terminal 5.8 00:11.59 9 3 360+ 37M+ 8308K+ 4944K- 99955
71182 ?~\~I?~A~S? 2.3 03:44:33 23/1 1 448 1186MK 0B 849M 71161
90322 ~QQ?~T 1.8 87:41.26 22 2 1356 436M 48K 353M 90322
90235 QQMusic 1.3 65:07.10 38 2 30907 181M 220K 108M 90235
79337 AlipayDispat 0.9 55:02.47 11 1 85 7140K 0B 2440K 79337
71175 ?~\~I?~A~S? 0.86 56:24.18 14 1 62 179M+ 0B 47M 71161
62136 ~AtomT 0.5 02:11:27 28 1 415 119M+ 0B 98M 62136
79482 WeChat 0.5 21:11.83 46 14 1043 338M 0B 188M 79482
71161 ?~\~I?~A~S? 0.4 26:00.58 37 1 494 125M+ 0B 84M 711618
57387 ~Google Chrom 0.3 00:20.55 16 1 146 78M 0B 8208K 80398
56497 Google Chrom 0.2 02:56.28 22 1 381 130M 0B 31M
本质上,看待进程与线程的区别,则不得不从占有地址空间、切换开销、并发性等方面展开分析:
1.从地址空间方面看,进程运行起来后时具有独立的地址空间,而线程具有的是独享的堆栈和局部变量,不存在单独地址空间一说。
2.关于切换开销方面,进程上下文的切换时间开销远大于线程,如果有多个进程提供服务客户端不得不通过负载均衡机制去切换个进程,而线程则通过线程池来维护在服务内部即可完成切换。
3. 操作系统按进程分配分配算力,一个进程的内即使有再多的线程,也只能得到一个CPU核心的算力,单靠进程的增加提升服务能力显然是有限得。而线程则是通过轮流排队申请CPU,则可以的充分利用CPU的能力以最小单位提升并发处理能力。
4. 每个独立的进程都有一个程序运行的入口、顺序执行序列和程序的出口,但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制;也就是不能要求别人在服务器上起一个线程或者杀死一个线程,但可以要求启动一个进程或者通过kill命令停止一个进程。
5. 系统在运行的时候会为每个进程分配不同的内存空间,比如我们为jvm应用指定堆内存大小;而对线程而言,除了 CPU 外,系统不会为线程分配内存,线程组之间只能共享资源,我们经常提到的HashTable线程安全、HashMap线程不安全也就是这么来的。
6. 进程之间是相互隔离得,即使一个进程出现故障挂了也不会影响其他进程的运行,比如在你的电脑上QQ挂了不会影响浏览器打不开。但线程之间则不是这样得,当线程池里的某个线程出现了故障,则其他线程也不得安宁,比如主线程因异常退出则所创建的异步线程池也随机损毁。