Java并发编程之进程与线程

引子

今天我们来探讨一下并发编程的相关内容, 首先我们思考的问题是为什么需要并发,并发解决了什么问题, 要理解这个问题,我们先来看看进程和线程的概念

进程和线程

我们先理解一下什么是进程

进程是具有一个独立的执行环境。通常情况下,进程拥有一个完整的、私有的基本运行资源集合,每个进程都有自己的内存空间 , 进程往往被看作是程序或应用的代名词

简单来说进程就是程序执行的一个实例.

我们再回顾一下计算机发展的历史,一开始我们使用批处理的计算机系统,

批处理

程序排队依次运行,一个cpu只能同时只能运行一个程序.

但是因为CPU处理的速度太快了,寄存器仅仅能够追的上他的脚步,内存和其他设备完全是望其项背,所以导致cpu一直在等待一些IO操作而导致资源的浪费,人们想提高资源利用率,所以人们提出了多任务系统.

多任务

所谓多任务系统就是每个进程系统分配了固定的执行时间,轮流的执行,所以当固定的时间片用完或者当程序遇到IO操作导致阻塞的时候,系统都会对进程进行上下文切换,切换的时候进程需要保存打开的文件句柄,程序段和数据段的地址,已经使用CPU的时间,等待CPU的时间等程序运行的信息,方便下次运行的时候恢复程序当前的状态,进程会保存到一个阻塞队列中等待IO操作完成了,就会进入就绪队列等待再次运行.

这样虽然在同一时刻只有一个程序在运行, 但是有很多程序在短时间内不断的切换, 在外界看来,似乎多个程序在同时执行

线程

但是新的问题又出现了,现在的程序一般都有用户界面,比如文本编辑器,当人们在打字的时候,可能会有自动保存的功能,自动保存文字是和IO打交道,那硬盘有多慢你也知道,因为IO阻塞了这时候操作系统会把整个进程挂起, 给人类的感觉就是: 程序死了,键盘和鼠标不响应了! 无法继续输入文字, 但是过一会儿就好了.

人们一开始想用多个进程来实现这个功能,但是多个进程之间切换因为要保存上下文、调入上下文,一旦多了的时候,还是有一定的时间消耗的。 而且进程之间的资源又是相互独立的,进程通信的代价太大了. 为了进一步提高资源利用率,人们在进程中,引入了线程,可以认为线程是一种轻量级的进程,运行在进程的内部,所以可以共享进程的所有资源,例如地址空间,全局变量,文件资源等等 但是每个线程也有自己独特的部分, 那就是要记住自己运行到哪一行指令了, 有自己的函数调用堆栈,自己的状态等等, 总而言之,就是为了能像切换进程那样切换线程, 这样我们就可以把用户界面和保存功能分为2个线程 保存导致的IO操作就不会阻塞用户界面了.

Java并发编程之进程与线程

线程的实现

关于线程的实现也有一些分歧,一种是希望在进程中实现,一种是希望在操作系统内实现

在进程中实现可以自己定制自己的调度算法,多灵活啊;
所有的线程切换都在进程内完成, 不用请求操作系统内核来处理,效率高, 但是存在一个致命问题,一旦其中一个线程阻塞了,系统就会认为整个进程阻塞了,从而会进行切换,那进程就不响应了. 所以实际上的实现上的实现是混合的一个实现 用户空间的进程可以创建线程(用户线程), 内核也会创建线程(内核线程), 用户线程映射到内核线程上从而可以接受操作系统的调度. Java并发编程之进程与线程

总结

那么为什么需要并发这个问题,我们大体上得出了答案, 就是为了提高系统的资源利用率和系统的吞吐量

我们可以使用进程或线程来实现并发, 但是由于多进程的资源消耗较大,并且进程通信不方便,所以我们进一步提出了线程作为我们并发的实现 现代的操作系统中线程是cpu调度的最小单元,而进程只是资源的分配的最小单元.

当然多线程编程过程会相对复杂,并且会出现多个线程同时操作同一个数据,导致线程安全问题, 这个问题我们下文继续探讨.

转载于:https://my.oschina.net/jayqqaa12/blog/1524176