本篇将会简单的介绍内核的同步入门简介
内核同步的简单概念
临界区
- 临界区这个词语听起来云里雾里的,但是其实很简单,就是一段代码段,这一段代码段可以访问共享资源
- 说的这么玄乎,其实我自己有简单的理解,就是将之类比称为被sync锁住的代码段,感觉意思差不多,有的时候我们通过sync锁住一段代码也是为了这段代码可以不被并发执行
内核中需要保护的资源
- 这个话题说起来有点搞笑,那就是linux内核中能够被并发访问的数据结构、资源基本上都需要被加锁保护,所以我们可以用反向思维,思考到底什么不需要被保护
- 只被特定线程访问
- 线程自己使用的资源
- 局部变量
内核同步方法
原子操作
原子操作非常容易理解,这里我直接引用Java中的一个结构,AtomicInteger,这个结构中的操作就是原子操作,linux内核里面也有类似的(说是类似其实只是感觉很像,这里我是为了自己方便理解)
自旋锁
- 自旋锁没有什么好说的,和我们平时理解的自旋锁没有什么区别,不过linux内核的自旋锁有一个非常非常坑的特性,那就是不可重入!
- linux的自旋锁不可以调用递归,因为linux的自旋锁是不可重入的,这就很操蛋,必须很小心的使用
读—写自旋锁
- 读写自旋锁,顾名思义,就是基于自旋锁的读写锁
信号量
- 乍一看这个好像不是什么锁,但是只是这么名字有点奇怪而已,这其实是Linux内核中的一种睡眠锁
- 顾名思义,这个锁可以让其他未获取锁资源的线程在等待队列中睡眠,直到这个锁资源被释放然后沉睡的线程被唤醒,起来获取锁资源
- 这个锁就可以类比Java里面的重量级锁
- 想要沉睡和唤醒一个线程的代价是很高的,所以这个信号量和自旋锁的适用情况和Java中Sync和CAS的适用条件是一致的
读—写信号量
- 没啥好说的,就是基于信号量实现的读写锁
互斥体
- 信号量比较适合于使用在那些状况复杂,情况未明的场景,对于简单场景不适用(重量大)
- 为了解决这个问题,人们开发出了互斥体(mutex),这是一个适用于简单场景的睡眠锁
- 说实话,mutex这个单词在Java的源码中就经常出现,例如在Collections.synchronizedMap()方法里面,被转换成为syncMap的hashmap里面,保证同步的sync锁锁住的就是一个被命名为mutex的obj对象
屏障
- 在linux内核里面,也存在屏障,这里面的屏障被称为barrier
- linux一共有三种屏障
- rmb:读屏障
- wmb:写屏障
- mb:混合屏障
小结
- 总而言之,以上的同步方法都是为了保证内核中的代码可以安全的执行,和Java中的锁机制有异曲同工之妙
文档信息
- 本文作者:JunHua yin
- 本文链接:https://yin-JH.github.io/2021/06/02/%E9%98%85%E8%AF%BB-Linux%E5%86%85%E6%A0%B8%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%AE%9E%E7%8E%B0-%E8%A1%A5%E5%85%85Linux%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%9F%A5%E8%AF%86%E7%B3%BB%E5%88%97(%E4%BA%94)%E4%B9%8B%E5%86%85%E6%A0%B8%E5%90%8C%E6%AD%A5%E7%AE%80%E4%BB%8B%E5%85%A5%E9%97%A8/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)