lock in OS
Posted xinfangzhang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lock in OS相关的知识,希望对你有一定的参考价值。
大意:
class Lock { acquire(val){ if(val==0){ val = 1; return false; }else{ return true } }; release(val){ val = 0; }; } let lock = new Lock(); let val =0; let checkLock = lock.acquire(val) while(checkLock){ //do nothing and wait; }; //run your code lock.release(val);
所谓的锁,本质上只是内存中的一个整形数,不同的数值表示不同的状态,比如1表示空闲状态和加锁状态。加锁时,判断锁是否空闲,如果空闲,修改为加锁状态,返回成功,如果已经上锁,返回失败,解锁时,就把锁状态修改为空闲状态。
加锁和解锁看起来都很简单,但是os是怎么保证锁操作本身的原子性呢? 在多核环境中,两个核上的代码同时申请一个锁,两个核同时读取锁变量,同时判断锁是空闲的,再各自修改锁变量为上锁状态,都返回成功,这样两个核同时获取到了锁, 这种情况可能吗? 当然是不可能的,那么os是通过什么手段来保证锁操作本身的原子性的呢?我们可以把上锁的过程具体表示为:
- 读内存表示锁的变量
- 判断锁的状态
- 如果已经加锁,返回失败
- 把锁设置为上锁状态,
- 返回成功
上面的每一个步骤都对应一条汇编语句,可以认为这每一步操作都是原子的,什么情况会导致两个线程同时获取到锁?
- 中断: 当线程A执行完第一步后,发生了中断,os调度线程B,线程B也来加锁并且加锁成功,此时又发生中断,OS调度线程A执行,从第二步开始,也加锁成功。
- 多核: 见上面例子。
那么怎么解决呢? 能不能让硬件做一种加锁的原子操作呢? 大名鼎鼎的“test and set”指令就是做这个事情的,该指令将读取内存、判断和设置值作为一个原子操作。单核环境下,锁的操作肯定是原子性了,多核呢?貌似还是不行,因为多个核心他们的锁操作是没有干扰的,都能够同时执行“test and set”,还是会出现两个线程同时获取到锁的情况, 所以硬件提供了锁内存总线的机制,在锁内存总线的状态下执行“test and set”操作就可以保证一个只有一个核执行成功,也就保证了不会存在多线程获取到锁的情况。
以上是关于lock in OS的主要内容,如果未能解决你的问题,请参考以下文章
一旦单击带有 in 片段的回收器列表项,如何将片段意向活动,以及如何获取回收器项目值?
并发包java.util.concurrent.locks.Lock
What's the difference between @Component, @Repository & @Service annotations in Spring?(代码片段
ElasticSearch学习问题记录——Invalid shift value in prefixCoded bytes (is encoded value really an INT?)(代码片段