您的位置:首页 > 其它

向下之旅(十二):内核同步介绍

2016-03-21 15:19 141 查看
  共享内存的应用程序必须特别留意保护共享资源,防止共享资源被并发的访问。内核也不例外。共享资源之所以要防止并发访问,是因为如果多个执行线程同时访问和操作数据,就有可能发生各线程之间相互覆盖共享数据的情况,造成被访问数据处于不一致状态。并发访问共享数据是造成系统不稳定的一类隐患。

  临界区和竞争条件

  临界区就是访问和操作共享数据的代码段。为了避免在临界区发生并发访问,编程者必须保证这些代码原子的执行——也就是说,代码在执行结束前不能被打断,如果两个执行线程有可能处于同一个临界区中,那么这就是程序包含的一个Bug。如果这种情况发生了,被称为竞争条件。避免并发和防止竞争条件被称为同步。

  加锁

  当出现并发线程访问共享数据的时候,此时需要给共享数据加锁,当获得锁的线程执行的时候,其他线程需等待,当线程执行完释放锁的时候,下一个线程获得锁,并重复执行上面任务。

  


  锁的使用是自愿的,非强制的,它完全属于一种编程者自选的手段。没有什么可以强制编程者在操作我们虚构的队列时必须使用锁。当然,如果不这么做,无疑会造成竞争条件而破坏队列。

  并发的产生

  用户进程可能在任何时刻被抢占,而调度程序完全可能选择两一个高优先级的进程到处理器上执行,所以就有可能在一个程序正处于临界区时,就被非自愿的抢占了,如果新调度的程序随后也进入同一临界区,此时,前后两个进程相互之间就会产生竞争。这里其实想着并不真是同事发生的,但他们相互交叉进行,所以也可被称为伪并发执行。

  如果是一个对称多处理机器,那么两个进程就可以真正的在临界区中同时进行了,这种类型被称为真并发。

  内核中有类似可能造成并发执行的原因。它们是:

  1.中断——中断几乎可以在任何时刻异步发生,也就可能随时打断当前正在执行的代码

  2.软中断和tasklet——内核能在任何时候唤醒或调度软中断和tasklet,打断当前正在执行的代码

  3.内核抢占——因为内核具有抢占性,所以内核中的任务可能会被另一任务抢占。

  4.睡眠及用户空间的同步——在内核执行的进程可能会睡眠,这就会唤醒调度程序,从而导致调度一个新的用户进程执行

  5.对称多处理——两个或多个处理器可以同时执行代码

  死锁

  死锁的产生需要一定的条件:要有一个或多个执行线程或一个或多个资源,每个线程都在等待其中一个资源,但所有的资源都已经被占用了。所有线程都在相互等待,但它们永远不会释放已经占有的资源。于是热河线程都无法继续,这便产生了死锁。

  自死锁:一个线程视图去获得一个自己已经持有的锁,它将不得不等待锁被释放,但是却又不释放锁。

  


  ABBA死锁

  


  通过一些手段可预防死锁:

  1.加锁的顺序是关键。使用嵌套的锁时必须保证以相同的顺序获取锁,这样可以阻止致命拥抱类型的锁。

  2.防止发生饥饿

  3.不要重复请求同一个锁

  4.越复杂的加锁方案越有可能造成死锁——设计应求简单。

  争用和扩展性

  锁的争用,是指当锁正在被占用的时候,有其他的线程试图获得该锁。当一个锁处于高度争用的状态时,说明有多个线程在等在获得该锁。锁的使用会降低系统的性能。

  扩展性是对系统可扩展程度的一个量度,对于操作系统,我们在谈及可扩展性的时候就会和大量的进程、处理器、或是大量的内存等联系起来。其实任何可以别计量的计算机组件都可以涉及可扩展性。

  参考自:《Linux Kernel Development》.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: