单核,多核CPU的原子操作

本文总结了多线程编程中的锁机制,解释了如何保证原子操作的实现,尤其是在单核和多核CPU环境下。通过关中断、硬件指令如test and set以及锁内存总线等手段,确保了在并发环境中的数据一致性。还探讨了原子操作的重要性以及Linux提供的原子操作接口。
摘要由CSDN通过智能技术生成

最近面试关于多线程加锁的一些问题总结于此:

在多线程编程中,为了保证数据操作的一致性,操作系统引入了锁机制,用于保证临界区代码的安全。通过锁机制,能够保证在多核多线程环境中,在某一个时间点上,只能有一个线程进入临界区代码,从而保证临界区中操作数据的一致性。

所谓的锁,无非就是内存中的一个整数,拥有两种状态:空闲状态和上锁状态.

那么OS如何保证锁操作本身的原子性的呢?

为了弄明白锁的实现原理,我们首先看看如果OS不采用任何其他手段,什么情况下会导致上锁失败?假如我们把加锁过程用如下伪码表示:
1、read lock;
2、判断lock状态;
3、如果已经加锁,失败返回;
4、把锁状态设置为上锁;
5、返回成功。
明白汇编的同学一看就明白上述每一步都能对应到一条汇编语句,所以我们可以认为每一步本身是原子的。


那么什么情况下会导致两个线程同时获取到锁呢?

1 中断:假设线程A执行完第一步,发生中断,中断返回后,OS调度线程B,线程B也来加锁并且加锁成功,这时OS调度线程A执行,线程从第二步开始执行,也加锁成功。

2 多核:因为多线程共享存储,有可能同时访问这个变量.


明白了失败原因,解决手段也就明确了.

先看单核场景:

1 关中断,加锁完成之后再开中断

2 关中断有可能效率不高,硬件中有一种指令叫做 test and set是原子操作可以用来实现锁.


那么对于多核环境下呢?

关键点在于两个核会并行操作内存而且从操作内存这个角度来看"test and set"不是原子性的,需要先读内存然后再写内存,如果能够保证这个内存操作是原子的,就能保证锁的正确性.硬件提供了锁内存总线的机制,我们在锁内存总线的状态下执行test and set操作,就能保证同时只有一个核来test and set.


总结一下,在硬件层面CPU提供了原子操作、关中断、锁内存总线的机制;OS基于这几个CPU硬件机制,就能够实现锁;再基于锁,就能够实现各种各样的同步机制(信号量、消息、Barrier等等等等)。所以要想理解OS的各种同步手段,首先需要理解本文介绍的内容,这时最原点的机制,所有的OS上层同步手段都基于此。


一. 何谓"原子操作":
原子操作就是: 不可中断的一个或者一系列操作, 也就是不会被线程调度机制打断的操作, 运行期间不会有任何的上下文切换(context switch).

二. 为什么关注原子操作?
1. 如果确定某个操作是原子的, 就不用为了去保护这个操作而加上会耗费昂贵性能开销的锁. - (巧妙的利用原子操作和实现无锁编程)
2. 借助原子操作可以实现互斥锁(mutex). (linux中的mutex_lock_t)
3. 借助互斥锁, 可以实现让更多的操作变成原子操作. 

三. 单核CPU的原子操作:
在单核CPU中, 能够在一个指令中完成的操作都可以看作为原子操作, 因为中断只发生在指令间.

四. 多核CPU的原子操作:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值