存在共享资源(共享一个文件,一块内存等等)的时候,为了防止并发访问时共享资源的数据不一致,引入了同步机制。

主要内容:

  1. 同步的概念
  2. 同步的方法-加锁
  3. 死锁
  4. 锁的粒度

1. 同步的概念

了解同步之前,先了解另外2个概念:

  • 临界区   - 也称为临界段,就是访问和操作共享数据的代码段。
  • 竞争条件 - 2个或2个以上线程在临界区里同时执行的时候,就构成了竞争条件。

所谓同步,其实防止在临界区中形成竞争条件。

如果临界区里是原子操作(即整个操作完成前不会被打断),那么自然就不会出竞争条件。

但在实际应用中,临界区中的代码往往不会那么简单,所以为了保持同步,引入了锁机制。

2. 同步的方法-加锁

为了给临界区加锁,保证临界区数据的同步,首先了解一下内核中哪些情况下会产生并发。

内核中造成竞争条件的原因:

竞争原因

说明

中断 中断随时会发生,也就会随时打断当前执行的代码。如果中断和被打断的代码在相同的临界区,就产生了竞争条件
软中断和tasklet 软中断和tasklet也会随时被内核唤醒执行,也会像中断一样打断正在执行的代码
内核抢占 内核具有抢占性,发生抢占时,如果抢占的线程和被抢占的线程在相同的临界区,就产生了竞争条件
睡眠及用户空间的同步 用户进程睡眠后,调度程序会唤醒一个新的用户进程,新的用户进程和睡眠的进程可能在同一个临界区中
对称多处理 2个或多个处理器可以同时执行相同的代码

为了在编写内核代码时避免出现竞争条件,在编写代码之前就要考虑好临界区在哪,以及怎么加锁。

在编写完代码后再加锁是非常困难的,很可能还会导致部分代码重写。

编写内核代码时,时时记着下面这些问题:

  1. 这个数据是不是全局的?除了当前线程以外,其他线程能不能访问它?
  2. 这个数据会不会在进程上下文或者中断上下文中共享?它是不是要在两个不同的中断处理程序中共享?
  3. 进程在访问数据时可不可能被抢占?被调度的新程序会不会访问同一数据?
  4. 当前进程会不会睡眠(或者阻塞)在某些资源上,如果是,它会让共享数据处于何种状态?
  5. 怎样防止数据失控?
  6. 如果这个函数又在另一个处理器上被调度将会发生什么?

3. 死锁

死锁就是所有线程都在相互等待释放资源,导致谁也无法继续执行下去。

下面一些简单的规则可以帮助我们避免死锁:

  1. 如果有多个锁的话,尽量确保每个线程都是按相同的顺序加锁,按加锁相反的顺序解锁。(即加锁a->b->c,解锁c->b->a)
  2. 防止发生饥饿。即设置一个超时时间,防止一直等待下去。
  3. 不要重复请求同一个锁。
  4. 设计应力求简单。加锁的方案越复杂就越容易出现死锁。

4. 锁的粒度

在加锁的时候,不仅要避免死锁,还需要考虑加锁的粒度。

锁的粒度对系统的可扩展性有很大影响,在加锁的时候,要考虑一下这个锁是否会被多个线程频繁的争用。

如果锁有可能会被频繁争用,就需要将锁的粒度细化。

细化后的锁在多处理器的情况下,性能会有所提升。

举个例子说明一下:比如给一个链表加锁,同时有A,B,C 3个线程频繁访问这个链表。

那么当A,B,C 3个线程同时访问这个链表时,如果A获得了锁,那么B,C线程只能等待A释放了锁后才能访问这个链表。

如果A,B,C 3个线程访问的是这个链表的不同节点(比如A是修改节点listA,B是删除节点listB,C是追加节点listC),

并且这3个节点不是连续的,那么3个线程同时运行是不会有问题的。

这种情况下就可以细化这个锁,把加在链表上的锁去掉,改成把锁加在链表的每个节点上。(也就是锁粒度的细化)

那么,上述的情况下,A,B,C 3个线程就可以同时访问各自的节点,特别是在多处理器的情况下,性能会有显著提高。

最后还有一点需要提醒的是,锁的粒度越细,系统开销越大,程序也越复杂,所以对于争用不是很频繁的锁,就没有必要细化了。

《Linux内核设计与实现》读书笔记(九)- 内核同步介绍的更多相关文章

  1. Linux内核设计与实现读书笔记(8)-内核同步方法【转】

    转自:http://blog.chinaunix.net/uid-10469829-id-2953001.html 1.原子操作可以保证指令以原子的方式执行——执行过程不被打断.内核提供了两组原子操作 ...

  2. Linux内核设计与实现 读书笔记 转

    Linux内核设计与实现  读书笔记: http://www.cnblogs.com/wang_yb/tag/linux-kernel/ <深入理解LINUX内存管理> http://bl ...

  3. Linux内核设计与实现——读书笔记2:进程管理

    1.进程: (1)处于执行期的程序,但不止是代码,还包括各种程序运行时所需的资源,实际上进程是正在执行的 程序的实时结果. (2)程序的本身并不是进程,进程是处于执行期的程序及其相关资源的总称. (3 ...

  4. 《Linux内核设计与实现》笔记-1-linux内核简单介绍

    一.Linux内核相对于传统的UNIX内核的比較: (1):Linux支持动态内核模块. 虽然Linux内核也是总体式结构,但是同意在须要的时候动态哦卸除(rmmod xxx)和载入内核模块(insm ...

  5. Linux内核设计与实现 读书笔记

    第三章 进程管理 1. fork系统调用从内核返回两次: 一次返回到子进程,一次返回到父进程 2. task_struct结构是用slab分配器分配的,2.6以前的是放在内核栈的栈底的:所有进程的ta ...

  6. Linux内核设计与实现——读书笔记1:内核简介

    内核:有的时候被称管理者或者操作系统核心,通常内核负责响应中断的中断服务程序, 负责管理多个进程从而分享处理器时间的调度程序,负责管理进程地址空间德内存管理程序 和网络,进程间通信等系统服务程序共同组 ...

  7. Linux Shell脚本攻略 读书笔记

    Linux Shell脚本攻略 读书笔记 这是一本小书,总共253页,但内容却很丰富,书中的示例小巧而实用,对我这样总是在shell门前徘徊的人来说真是如获至宝:最有价值的当属文本处理,对这块我单独整 ...

  8. 【2018.08.13 C与C++基础】C++语言的设计与演化读书笔记

    先占坑 老实说看这本书的时候,有很多地方都很迷糊,但却说不清楚问题到底在哪里,只能和Effective C++联系起来,更深层次的东西就想不到了. 链接: https://blog.csdn.net/ ...

  9. 《Linux内核分析与设计实现》读书笔记一

    第一章 Linux内核简介 1.1 Unix的历史 Unix的特点: Unix很简洁,仅仅提供几百个系统调用并且有一个非常明确的设计目的: 在Unix中,所有的东西都被当做文件对待. Unix的内核和 ...

  10. 初探内核之《Linux内核设计与实现》笔记上

    内核简介  本篇简单介绍内核相关的基本概念. 主要内容: 单内核和微内核 内核版本号 1. 单内核和微内核   原理 优势 劣势 单内核 整个内核都在一个大内核地址空间上运行. 1. 简单.2. 高效 ...

随机推荐

  1. How To Uninstall Software Using The Ubuntu Command Line

    How To Uninstall Software Using The Ubuntu Command Line Uninstall Ubuntu Software Using The Terminal ...

  2. 如何上Chrome谷歌商店

    将以下代码复制到本地Hosts中即可. #Google Services START64.233.162.83 0.docs.google.com64.233.162.83 0.drive.googl ...

  3. Python函数-map()

    map()函数 map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回.如下: def ...

  4. 修改分区后的 Grub rescue

    声明:这里用到的知识不是原创,综合了几篇教程的成果.找的时候比较混乱,所以来源已经不确定.希望原作者见谅. 系统是Windows 8.1 和 Ubuntu 14.04, Windows是先装的, gr ...

  5. 前端跨域问题,以及ajax,jsonp,json的区别

    看了很多网上的资料,小七感觉都没有完全解决我的疑惑以及问题,所以特意拿出通俗易懂的话讲解跨域问题,以及ajax,jsonp,json的区别.首先先说跨域问题什么时候需要跨域?[1]域名不同(即网址不同 ...

  6. jquery-post 异常

    报错:Client closed connection before receiving entire response 前端请求: $.ajax({ type : 'POST' , url : '/ ...

  7. linux 内存释放命令

    我使用的是CentOS 6.5 ,由于卸载Solr 后发现内存占用挺多的,我想释放一下内存,就查阅了一些资料,分享给大家: 1.free -m  查看内存的使用情况,-m表示单位是兆 2.echo 1 ...

  8. Docker持续化集成和测试

     基于容器的自动构建:Docker在美团的应用 https://linux.cn/article-5465-1.html Docker持续化集成和测试,关于docker-in-docker问题 h ...

  9. 2014.2.23 datagridview显示图片的方法

    DataTable dt = new DataTable(); dt.Columns.Add("", typeof(byte[])); dt.Rows.Add(File.ReadA ...

  10. nginx for windows之负载均衡

    1.编辑c:\nginx\conf\nginx.conf   添加以下内容: #user  nobody;   #启动进程worker_processes  1;   #全局错误日志及PID文件err ...