并发:是指两个或更多独立的活动同时发生,在单个系统里同时执行多个独立任务,而非顺序地进行一些活动。同一时间内可以交替处理多个操作,有竞争。如:两队安检队列队首的人竞争谁先过这一安检窗口
图中整个安检系统是一个并发设计的结构。两个安检队列队首的人竞争这一个安检窗口,两个队列可能约定交替着进行安检,也可能是大家同时竞争安检窗口(通信)。后一种方式可能引起冲突:因为无法同时进行两个安检操作。在逻辑上看来,这个安检窗口是同时处理这两个队列。
并行:同一时间内处理多个操作,没有竞争关系。
图中整个安检系统是一个并行的系统。在这里,每个队列都有自己的安检窗口,两个队列中间没有竞争关系,队列中的某个排队者只需等待队列前面的人安检完成,然后再轮到自己安检。在物理上,安检窗口同时处理这两个队列。
并发的程序设计,提供了一种方式让我们能够设计出一种方案将问题(非必须地)并行地解决。如果我们将程序的结构设计为可以并发执行的,那么在支持并行的机器上,我们可以将程序并行地执行。因此,并发重点指的是程序的设计结构,而并行指的是程序运行的状态。并发编程,是一种将一个程序分解成小片段独立执行的程序设计方法。
老:单个处理器,某一时刻执行一个任务,可以每秒进行多次任务切换
新:多核处理器,真正的并行多核任务,同时也可以进行任务切换
系统从一个任务到另一个任务(即进行切换),要进行一次上下文切换,切换时,操作系统必须为当前运行的任务保存CPU的状态和指令指针,并计算出要切换到哪个任务,并为即将切换到的任务重新加载处理器状态。然后,CPU将新任务的指令和数据的内存载入缓存中。
进程切换:从正在运行的进程中收回处理器,实质是把进程存放在处理器的寄存器中的中间数据找个地方存起来,从而把处理器的寄存器腾出来,让其他进程使用。被终止运行进程的中间数据被存放在进程的私有堆栈。
让进程来占用处理器,实质上是把某个进程存放在私有堆栈中寄存器的数据(前一次本进程被中止时的中间数据)再恢复到处理器的寄存器中去,并把待运行进程的断点送入处理器的程序指针PC,于是待运行进程就开始被处理器运行了,也就是这个进程已经占有处理器的使用权了。
多进程并发:
这种进程间通信设置复杂,速度慢,因为操作系统会在进程间提供一定的保护措施,以避免一个进程去修改另一个进程的数据,另一个缺点是,运行多个进程所需的固定开销,需要时间启动进程等。
优点是:因为进程间有保护,更容易编写安全的并发代码等。
多线程并发:
一个进程中的所有线程,共享地址空间,并且线程访问到大部分数据可以在线程之间传递,地址共享,缺少线程间数据保护,使操作系统的记录工作量减小,多线程开销远远小于多进程。
共享内存有代价:数据要被多个线程访问,必须保证每个线程所访问到的数据是一致的。
线程是有限的资源,太多线程同时运行会消耗很多操作系统资源,从而使操作系统整体上运行得更加缓慢。
每线程需要一个独立的堆栈空间,运行太多的线程会耗尽进程的可用内存或地址空间。
每个线程都会有一个1MB的堆栈(很多系统都会这样分配),对于一个可用地址空间4GB(32bit)的平坦架构的进程来说,4096个线程会用尽所有地址空间,不会给代码,静态数据或者堆数据留有任何空间。
运行越多线程,操作系统就要做越多的上下文切换。