关于   小悟志   栏目   标签   文章   归档   友链

   云上小悟  +  

当前位置 : 首页 » InfoTech » 进程(线程)同步 正文

进程(线程)同步

InfoTech / by: 麦新杰 / 发布:2017年7月4日 / 8次阅读 / 暂无评论
标签:计算机   / 最后修改时间: 2017-07-06 09:05:56

InfoTech / 2017年7月4日 / 8次阅读 / 标签:计算机  

拍拍贷
featured image

在计算机操作系统的教科书中,进程(线程)同步这个章节恐怕是难度最大的章节之一。要想深刻地理解底层原理,必须要深入到底层的细节中去,而教科书一般都不会,或者很难把很多底层的细节全部展现出来。好吧,麦新杰来尽量按照自己的思路总结一下,说得不对请指正。

 

同步和异步是什么意思?

同步,就是协同,多进程(线程)运行环境,只要两个执行序列之间存在某种关联,就存在同步;比如阻塞,就是同步的一种,阻塞是需要等待,没有关联干什么要等呢。

异步就是非同步,两个执行序列之间完全没有关系,各干各的,他们之间的交错调度完全依赖OS的调度,而且,OS就算交错调度它们,也并不是因为它们之间有什么关系。

 

什么情况下需要同步?

这里不讨论上层应用的逻辑,比如A事情做完了,再做B事情,这时你完全可以先运行A程序,待A程序结束后,再运行B程序。

我们讨论底层机制,比如当两个在内存中的进程(线程)都有修改同一个变量C的需求的时候,这两个进程之间就需要同步,需要协调一下,不能出现在同一时刻修改C变量的情况发生。因为,如果两个进程(线程)同一时刻去修改C变量,可以导致C变量的值发生逾期之外的变化。再比如A进程在执行到某个地方的时候,要等待B进程执行过某个点后,才能继续。

有个专业术语叫race condition(竞争条件),发生race condition的原因是高级语言的一条写语句,编译为底层机器指令是多条指令,这多条语句之间可能会被中断(中断发生在指令之间,中断可以发生在任何时候),多个进程对同一个内存地址的写操作,在中断的因素下交错执行,这个内存地址的内容将不可预知。因此,需要同步,一个时间段,只能有一个进程写入(原子操作,即不可被中断的操作),其它进程要想写,先等等。

(这里没有考虑CPU的cache,比如一个写操作,CPU会不会先写入cache,然后再后续某个时点,再写入内存?我们只考虑直接写内存的情况。)

通过软件的方式来实现同步的思路有Peterson算法(据说在某些CPU上,由于load和store指令的某些原因,导致这个算法失效了);通过硬件的方式同步,就是CPU要提供能够原子的执行的操作指令;不过,编写程序,一般都是使用信号量。

 

内核抢占,非内核抢占

OS在内存中有许多全局的共享数据结构,这些数据结构维持着整个系统的正常运转,同时,这些数据结构有可能会同时被多个进程修改。

所谓非内核抢占,就是指,OS在内核模式的情况下,中断是被关闭的,这时不会发生进程的上下文切换,也就从更本上规避了多个进程同时修改内核数据的可能性。这是一个简单的思路,Windows XP,Linux 2.6之前都是非内核抢占模式。非内核抢占只是针对内核数据的保护,对于进程自己的共享数据,还是存在同步的需求。

非内核抢占采用的是在内核模式关闭中断的方法,可以想象一下,中断一旦被关闭,CPU将无法响应任何IO请求,这回带来响应时间和实时性方面的问题,因为,后来又出现内核抢占这种模式。

所谓内核抢占,就是在内核模式下,进程之间依然可以被抢占;显然,内核抢占模式下,中断是没有被关闭的。内核抢占模式更受欢迎,因为这个特性带来更好的实时性。

 

多对一的线程模式不需要同步

多对一的线程模式,由于多个线程的调度发生在进程空间,因此不需要同步。这样的运行机制,即每个线程都必须要执行完毕之后,才有可能调度另外的线程,所以不可能出现race condition。

多对一的线程模式有点像非内核抢占。

 

信号量和互斥量

信号量和互斥量其实本质上同样的东西,区别是,信号量的值域范围很大,而互斥量只有0和1;如果把信号量的取值限定在0和1,信号量就成了互斥量。

信号量和互斥量就是一把锁,lock,程序执行到关键区域(critical section,国内教科书也有翻译为临界区,我很不喜欢这个翻译,字面含义与实际意思相去甚远)时,要先获取这个lock,获取不到就只能等,获取到了才能继续执行这个critical section,执行完后释放锁。这就是我们常常说的PV操作(PV是两个荷兰语的首字母,分别表示wait和signal的含义)

wait一个信号量,这时不能是死等(忙等,这样的锁叫spinlock),这样太浪费资源了。实践是判断lock是否available,如果不是,就阻塞进入等待(每个信号量都有一个专有的等待队列),而在signal动作中,wakeup一个等待此信号量的进程。注意,wait和signal(或者PV操作)都是原子操作,实现原子操作的方法就是:关闭中断,或者使用CPU提供的原子操作指令。

有了PV操作,并不可以高枕无忧,在变成时,还要小心死锁(deadlock)和饥饿(starvation)。死锁就是两个进程都在等待对方释放一个资源,而每个进程都只能获得对方的资源后才能释放资源,经典的死锁模型就是哲学家吃饭的问题。饥饿是在等待某个信号量的队列中,有进程因为调度的原因,始终得不到运行的机会,这种场景饥饿的问题几乎不会存在;比较容易出现饥饿的是经典的读者-写者问题,不管是读优先,还是写优先,都有可能导致饥饿。

信号量和互斥量很常用!

 

读写锁

读写锁(Read-Write Lock)致力于一种更加特定的场合的同步。

对于一段数据,多个线程同时读取总是没有问题的,但假设操作都不是原子型,只要有任何一个线程试图对这个数据进行修改,就必须使用同步手段来避免出错。如果我们使用上述信号量、互斥量或临界区中的任何一种来进行同步,尽管可以保证程序正确,但对于读取频繁,而仅仅偶尔写入的情况,会显得非常低效。读写锁可以避免这个问题。对于同一个锁,读写锁有两种获取方式,共享的(Shared)或独占的(Exclusive)。

当锁处于自由的状态时,试图以任何一种方式获取锁都能成功,并将锁置于对应的状态。如果锁处于共享状态,其他线程以共享的方式获取锁仍然会成功,此时这个锁分配给了多个线程。然而,如果其他线程试图以独占的方式获取已经处于共享状态的锁,那么它将必须等待锁被所有的线程释放。相应地,处于独占状态的锁将阻止任何其他线程获取该锁,不论它们试图以哪种方式获取。

 

--------我是单CPU和多CPU(SMP)的分割线---------

 

以上内存都是在说单CPU的情况,而多CPU体系的计算机,比如常见的SMP,情况要更加复杂一些。这方面的资源,国外的教科书上也不多。麦新杰仅将一些个人知道的知识点列出。

 

spinlock(自旋锁)

前面提到过spinlock,这类信号量就是在wait的时候忙等死等。

如果设计优良,spinlock可以用在SMP体系中来处理互斥的问题。这要求critical section的代码要简短,很快就能执行结束并释放锁,其它在spin的状态下等待的进程,就可以不用等太久。

因为spinlock是忙等,在单CPU体系下会有问题,因为一旦一个进程进入spin状态,将无法运行其它代码,因为中断也被关闭了,包括要释放锁的进程,这时我们通常称为死机。而在多CPU体系下,进程可以在不同的CPU上运行和等待,只要critical section足够短小精干,等待的时候就会很短,整个系统的运转会很顺畅。我想这就是spinlock在SMP体系下可以运用的原因吧。

 

这里有个问题:多CPU体系下,加入每个CPU上有一个进程,这些进程在同时进行wait操作,这时相互之间是如何协调的?

在单CPU下,可以通过关闭中断来实现。多CPU下,也是全局关中断吗?

spinlock的等待发生在wait这个操作里面,由于这个操作是原子的,在等待的过程中,死等,中断也关了(至少那个CPU的中断),如果多个CPU中的进程都进入wait状态,一旦锁被释放,多信号量的操作就不再是原子的了,这如何处理?

在别人的博文中看到这段话:

在x86体系中, CPU提供了HLOCK pin引线, 允许CPU在执行某一个指令(仅仅是一个指令)时拉低HLOCK pin引线的电位, 直到这个指令执行完毕才放开,从而锁住了总线, 如此在同一总线的CPU就暂时无法通过总线访问内存了, 这样就保证了多核处理器的原子性。

spin lock必须基于CPU的数据总线锁定, 它通过读取一个内存单元(spinlock_t)来判断这个spinlock是否已经被别的CPU锁住. 如果否, 它写进一个特定值, 表示锁定了总线, 然后返回。如果是, 它会重复以上操作直到成功, 或者spin次数超过一个设定值. 记住上面提及到的:锁定数据总线的指令只能保证一个指令操作期间CPU独占数据总线.

好复杂,都开始锁定总线了。我还是晕。

-- (*^-^*) --

本文链接:http://www.maixj.net/ict/tongbu-15886
云上小悟 麦新杰(QQ:1093023102)

《进程(线程)同步》暂无评论

电子邮件地址不会被公开。 必填项已用*标注


前一篇:
后一篇:

云上小悟独立博客网站文章内容,除非特别注明,全部都是原创(非原创请阅读本站版权声明),如需转载,请保留文章链接!原创文章更具个性,有些文字虽略显随意,但不影响个人思想表达。部分文章是我自己的笔记,为自己记录,总结和收藏,同时也分享给您!这是本博建设的出发点,希望您喜欢并得到您的支持!

©Copyright 麦新杰 Since 2014 云上小悟独立博客版权所有  备案号:苏ICP备14045477号-1  economists.cn的备案号:苏ICP备14045477号-3  
    联系我们

云上小悟,麦新杰的独立博客
网站二维码