标签:lock sha 变量 过程 同步 第一步 临界区 不能 sig
为了保证数据的一致性,在多线程编程中我们会用到锁,使得在某一时间点,只有一个线程进入临界区代码。虽然不同的语言可能会提供不同的锁接口,但是底层调用的都是操作系统的提供的锁,不同的高级语言只是在操作系统的锁机制基础上进行了些封装而已,要真正理解锁,还是得看操作系统是怎么实现锁的。
所谓的锁,本质上只是内存中的一个整形数,不同的数值表示不同的状态,比如1表示空闲状态和加锁状态。加锁时,判断锁是否空闲,如果空闲,修改为加锁状态,返回成功,如果已经上锁,返回失败,解锁时,就把锁状态修改为空闲状态。
加锁和解锁看起来都很简单,但是os是怎么保证锁操作本身的原子性呢? 在多核环境中,两个核上的代码同时申请一个锁,两个核同时读取锁变量,同时判断锁是空闲的,再各自修改锁变量为上锁状态,都返回成功,这样两个核同时获取到了锁, 这种情况可能吗? 当然是不可能的,那么os是通过什么手段来保证锁操作本身的原子性的呢?我们可以把上锁的过程具体表示为:
前面提到,cpu会通过对总线加锁的手段来解决多核同时获取锁的情况,它到时是怎么实现的呢? 在cpu芯片上有一个HLOCK Pin,可以通过发送指令来操作,将#HLOCK Pin电位拉低,并持续到这条指令执行完毕,从而将总线锁住,这样同一总线上的其他CPU就不能通过总线来访问内存了。最开始这些功能是用来测试cpu的,后来被操作系统实现而封装成各种功能:关键代码段,信号量等。
在加锁的代码编译成汇编后,会有个lock指令前缀:
Causes the processor‘s LOCK# signal to be asserted during execution of the accompanying instruction (turns the instruction into an atomic instruction). In a multiprocessor environment, the LOCK# signal insures that the processor has exclusive use of any shared memory while the signal is asserted.
lock会使得紧跟在其后的指令变成atomic instruction,暂时的锁一下总线,指令执行完,总线就解锁了。
在硬件层面,cpu提供了原子操作、锁内存总线等机制,OS根据这几个cpu硬件机制就能够实现锁,在基于锁,就能实现各种各样的同步机制(信号量、消息等等),要理解os提供的各种同步手段,需要先理解os是怎么实现锁的。
标签:lock sha 变量 过程 同步 第一步 临界区 不能 sig
原文地址:https://www.cnblogs.com/zl1991/p/12932173.html