java并发编程:进程和线程

先理解进程和线程有助于学习java并发编程。

进程的由来

为什么有进程:现在计算机的功能已经十分丰富了,可以一边看视频,一边浏览网页等等。但是在计算机开始出现的时候,计算机的功能十分简单,人们输入特定的指令,计算机就执行该指令,但是当人们休息或者思考的时候计算机就不工作,效率十分低下。

为了更好的利用计算机,人们把要执行的命令写下来,写在一个磁带上,让计算机去读取指令,然后执行指令,这样就提高了效率。这也就是批处理操作系统。

虽然这已经很优秀了,但还是有些问题,比如现在有两个任务A,B,A在执行的时候需要很多的IO操作,比如读取磁盘内容,而我们知道cpu很快,磁盘很慢,那么在读取磁盘的时候,cpu是空闲的。

解决办法:进程

在之前,内存中只有单独的一份数据,但是现在进程出现了,它要求内存中每一个程序都有一片属于自己的区域,每个区域互不干扰,而且保存了每个程序此时的状态,那么当A执行IO时,cpu空闲,此时cpu就可以执行B任务了。而且不止两个任务,还可以是多个,由于cpu的快速,使人们感觉多任务是在同时进行。

对于单核cpu来说,同一时刻只有一个进程占有cpu,至于那一个任务可以下一个占有cpu是不同的调度算法实现:比如先进先出,LRU,给予优先级,实现片轮转法等等。

线程的由来

进程仍然不能满足人们的需要,举个例子:在浏览器中,我们点击了下载按钮,那么此时浏览器的进程开始下载文件,如果此时cpu只是执行下载这个任务的话,显然我们就什么都干不了了。但是同时我们还想要浏览其他网页,还希望同时他开多个页面从服务端请求数据。

为了解决这个问题,线程出现了,线程可以说是轻量级进程(在linux中线程与进程区别很小),一个线程属于一个进程,一个进程可以有多个线程。也就是同一个进程下的线程是共享一片内存区域的,但是每个线程也有自己私有的数据比如程序计数器,调用栈等等。进程是资源分配的基本单位,线程是调度的基本单位。

当然同一时刻,一颗cpu依旧只能被一个线程占有,但是由于cpu强大的能力,看起来在一个进程中依旧是多任务执行的。

总体来说,进程的出现是为了提高计算机的利用率,线程的出现也是为了进一步提高计算机的利用率。

实际上再往下还有协程,go语言还有go程

java并发的问题

java作为一门强大的编程语言,也支持线程。

但是如果两个线程同时访问一个资源,而且这个资源只能同时被一个线程访问时,就需要进行同步问题。

比如:连个线程同时对一个文件进行写入,而没有先后顺序的话,那么这个文件就该删除了,因为没人能看得懂。

协程

进程与线程的调度都需要内核来完成,需要在用户态和内核态之间转换,因此效率较低。人们希望有可以不经过内核来完成调度,因此协程出现了。

协程的优势就是切换不需要经过内核,由用户控制,因此它更加轻量级。

但是对于单核CPU来说,同一时刻依旧只有一个协程用有CPU的使用权。

其他

并不是线程越多越好。

  1. 首先线程的切换是需要时间的,切换时需要保存此时线程执行的状态,然后载入将要执行的线程的状态
  2. 如果是cpu密集型,比如处理压缩视频,跑模型,需要大量的计算,那么没必要的线程切换反而会浪费cpu资源;如果是IO密集型,那么可以适当多增加线程,在响应IO是可以使用cpu干其他的事
  3. 选择是使用多进程还是多线程需要根据具体情况判断,譬如如果需要更快的响应速度,可以使用多线程;如果需要更加稳定可靠,对响应速度要求不高,可以使用多进程。

参考

https://www.cnblogs.com/dolphin0520/p/3910667.html

文章作者: gentlezuo
文章链接: http://gentlezuo.github.io/2019/06/09/java并发编程:进程和线程/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 gentlezuo的博客