原子操作

什么是原子操作,之前在线程同步 中提到过锁的概念,锁就是个原子操作,即锁实现的全部步骤必须看成一步,cpu切换的时候不能把原子操作切开。
  为什么不能切开了。用锁举例,我们在思考锁是如何运行的,简单的想,既然lock()为上锁,它起码要分为
1.判断是否还有锁
2.如果有锁就上锁,没锁就等着。
这俩步,这还是我们以宏观思维想的,然而计算机真正的要实现可能需要的步骤还要更多。
如果cpu切换的时候把  实现锁的代码从中切开,那就会产生临界区的问题,那么锁的意义就丧失了,因此我们规定了锁的实现是个原子操作,不能切开,要保护锁完整的功能。原子象征着不可分的粒子(当然现在有了夸克更小的分法,不过别较真儿,懂意思就行)。
  然而有人可能会觉得,如果能定义原子操作,那么何必还要锁呢?把需要锁的临界区代码也定义成原子操作那不更省事,何必多个锁步骤呢?
 其实简单来说,就是这个功能太强大了,系统不放心交给用户来随意定义,如果出错,会很难收拾,轻则搞垮系统,重则被人攻击。所以只将原子操作的定义交给了系统自己的系统函数。
  进程或线程的切换分为自发的和强制的。自发的是线程因功能需要等原因代码中调用yield放弃对cpu的占有,强制的是系统中断引起的,为了保证各进程间平衡。如果对我们程序员放权,随意使用原子操作,系统无法中断很可能出了bug的代码程序,这显然是不现实的。
  除了锁,信号量这些原语是原子操作,还有什么需要原子操作呢。
  其实很多很多,回想下文件输入输出那里的知识,进程切换间会存在什么问题需要原子操作来解决?
  我们知道原子操作就是为了防止临界区混乱,临界区混乱的原因就是对于共享资源数据的竞争导致的。
  一提起共享是不是立刻想到了文件共享?文件偏移量共享呢?
  假若一个程序 A和B 的操作都是在文件末尾写入数据。
 第一个A程序在检测到末尾的时候,切换为B程序,B程序也同样检测到和A一样的末尾,写入数据,然后再切换到A,A不会再次检测末尾了,直接也写入数据,这是不是就会发生A写的数据把B覆盖的情况?而我们的本意是让A,B程序交替运行,依次在末尾添加数据,数据都不能丢失的。
 这就是由于检测末尾lseek函数和write函数中间被进程切换了导致少判断了次偏移量。
 因此解决方法就是让lseek和write合成为一步原子操作,不可被中断,因此就有了pwrite函数,同理还有pread函数。这样就解决了进程同步中出现的问题。
   接触原子操作概念以前,我们很难想象如何改进代码来修改这种bug,因为中断属于系统级的权限,因此就需要比中断更高级的原子操作才能阻挡。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值