内核之锁

在并发中为了解决数据一致性问题,通常我们都会使用到加锁的方式来解决。
那么加锁原理是如何的那?让我们从宏观的角度来进行解析一下。

在第一个提供了SMP功能的内核版本中,该问题的解决方案非常简单,即每次只允许一个处理器处于核心态。因此,对数据未经协调的并行访问被自动排除了。令人遗憾的是,该方法因为效率不高,
很快被废弃了。

这种方式很合理,而且还特别好理解,只要让一个运行别的都不让进来将并行串行化不就解决这个问题了嘛!!!
但是想想锁住整个内核区,不就跟Mysql里面的MyISAM表锁一样没有InnoDB行锁并发效率高,这牵扯到一个锁的粒度问题。那么如果我们将锁的粒度提高些那

现在,内核使用了由锁组成的细粒度网络,来明确地保护各个数据结构。如果处理器A在操作数
据结构X,则处理器B可以执行任何其他的内核操作,但不能操作X。
也就是说,在内核中,内核是通过在一刻时间内只允许一个CPU内核来对并发数据进行操作。

RCU机制

RCU的原理很简单:该机制记录了指向共享数据结构的指针的所有使用者。在该结构将要改变时,则首先创建一个副本(或一个新的实例,填充适当的内容,这没什么差别),在副本中修改。在所有进行读访问的使用者结束对旧副本的读取之后,指针可以替换为指向新的、修改后副本的指针。请注意,这种机制允许读写并发进行!如果更新可能来自内核中许多地方,那么必须使用普通的同步原语防止并发的写操作,如自旋锁。尽管RCU能保护读访问不受写访问的干扰,但它不对写访问之间的相互干
扰提供防护!

其实这个机制就是系统里面的写时复制策略

缓冲区一致性问题

既然锁的原理明白了,让我们看看缓冲区的数据一致性问题。想想在JAVA里面为什么voliate可以保证可见性的那?
在操作系统中,每个CPU都有一个自己的高速缓冲区,那么cpu在操作数据的时候都会先把数据加载到缓冲区中。那么同样一个数据被多个CPU加载必定会出现数据的一致性问题在多个CPU同时对它进行写操作的时候。
为了解决这个问题操作系统使用了MESI协议。

MESI
MESI 是指4中状态的首字母。每个Cache line有4个状态,可用2个bit表示
M 修改 (Modified) E 独享、互斥 (Exclusive) S 共享 (Shared) I 无效 (Invalid)
通过CPU之间的通信机制,当一个CPU要写数据时会向其余CPU发送缓冲数据失效命令。当确认都收到信息后将数据写入内存中。

这里我们可以知道缓存一致性的原理,但是我们想想如果每次CPU在通知别的CPU该数据无效时都等待其他CPU的回应(同步操作)这样效率是不是大大的降低了。如果使用异步的方式进行操作性能上肯定能够得到提高。

Store Bufferes被引入使用。处理器把它想要写入到主存的值写到缓存,然后继续去处理其他事情。当所有失效确认(Invalidate Acknowledge)都接收到时,数据才会最终被提交。

但是这样做有两个风险

第一、就是处理器会尝试从存储缓存(Store buffer)中读取值,但它还没有进行提交。这个的解决方案称为Store Forwarding,它使得加载的时候,如果存储缓存中存在,则进行返回。
第二、保存什么时候会完成,这个并没有任何保证。
这种在可识别的行为中发生的变化称为重排序(reordings)

那么怎么解决这种办法?
在《Java并发编程的艺术 》一书中有章节讲到内存屏障的机制。没错解决这种办法的方式就是使用内存屏障来防止CPU进行重排序。

写屏障 Store Memory Barrier(a.k.a. ST, SMB, smp_wmb)是一条告诉处理器在执行这之后的指令之前,应用所有已经在存储缓存(store buffer)中的保存的指令。
读屏障Load Memory Barrier (a.k.a. LD, RMB, smp_rmb)是一条告诉处理器在执行任何的加载前,先应用所有已经在失效队列中的失效操作的指令。

voliate就是使用了MESI协议以及内存屏障的机制来保证的可见性问题。

还有个问题就是voliate为什麽不能保证 i++ 等操作的原子性那?
让我们把i++拆开来看

i = 2;
tmp = i + i;
i = tmp

两个CPU,A,B。
AB同时读取i到缓冲区中,然后进行tmp = i + i;操作将i的值放入tmp,然后当运行i=tmp时,会进行缓冲区无效操作,一方cpu向另一个cpu发送i数据无效操作。假设A向B发送了缓冲区无效操作,然后A将i回写到内存中,而这时,B开始运行i = tmp操作,虽然B会再次读取内存中的i但是tmp还是原来的值所以,当B将i回写到内存中其实是使用的tmp中的值。至此原子性被打破!

参考文献 《深入liunx内核架构》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值