并发引发的问题
——以线程(轻量化进程)为主体
不可否认,线程的引入,的确减小了程序在并发执行时系统所付出的时空开销,容许更多线程参与并发,从而提高了系统的并发性。但是,由并发引起的,线/进程间对于共享资源操作的敏感性,以及线程间资源高度共享的特征,也更突显了并发所导致的不可忽视的问题:临界资源访问、同步与互斥管理。
临界资源访问:
我们将一次仅允许一个进/线程使用的资源成为临界资源。
操作系统内,多个进程间可以共享系统中的各种资源,对应线程则共享程度更高,共享几乎进程内所有的资源,这些资源也即共享资源。资源共享提高了系统的共享特性,但也增加了共享资源管理的难度。因为其中许多资源一次只能为一个进/线程所用,否则将导致程序执行结果的不确定性。比如TEP书26.2中“打印A/B进程”的例子,结果不如理想的那样,B可能先执行,即便结果相同,执行的细节也多种多样。
执行结果的不确定性有两层含义:一、多线程执行次序的不确定性;二、线程原语执行效果的不确定性,对应于临界区访问的互斥要求。由此对应的两个关键概念是同步与互斥。
同步:
系统在调度线程进入阻塞或者就绪队列时,次序并不是“先来先服务”的,而是需要线程间协调次序、传递信息、阻塞等待,以完成某些任务,我们将这种直接制约关系称为同步。同步规范了同一进程下的某些线程并发执行时,需要遵守一定的次序,相互间同步操作,保障执行流按既定方向流逝。
互斥:
资源的共享本身并没有问题,但线程切换时,随时的、不确定的中断机制可能会打破理想的进程执行秩序,影响线程原语的执行效果。比如TEP书26.2中“两线程共享变量,并发执行累加10000000”的例子,两线程执行时由于中断的随机发生,并且在两线程间随意中断,程序执行的结果每次都不同。实际上,中断控制的粗粒度和原语切割的不合理,共同导致了上述两线程并发时,许多原语的作用被互相覆盖擦除了,没有产生实际效果。由此,现代计算机要求访问临界区时遵循互斥原则,一个线程进入临界区使用资源时,另一个线程必需等待其访问完成。
中断机制提升了同步与互斥问题的复杂程度,但中断机制是操作系统工作的关键,因此以上三个问题是并发执行时,进/线程调度管理不可避免的关键问题,也是关键难题。
以上我们知道了线程并发执行时,访问临界区资源需要满足同步与互斥,由此提出解决此问题的两种思路:超级指令“super instructions”和同步原语“synchronization primitives”。