码迷,mamicode.com
首页 > 其他好文 > 详细

lock in OS

时间:2020-03-05 15:19:38      阅读:32      评论:0      收藏:0      [点我收藏+]

标签:release   you   表示   修改   过程   读取   空闲   ase   ==   

 

大意:

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是通过什么手段来保证锁操作本身的原子性的呢?我们可以把上锁的过程具体表示为:

  1. 读内存表示锁的变量
  2. 判断锁的状态
  3. 如果已经加锁,返回失败
  4. 把锁设置为上锁状态,
  5. 返回成功
          上面的每一个步骤都对应一条汇编语句,可以认为这每一步操作都是原子的,什么情况会导致两个线程同时获取到锁?
  • 中断: 当线程A执行完第一步后,发生了中断,os调度线程B,线程B也来加锁并且加锁成功,此时又发生中断,OS调度线程A执行,从第二步开始,也加锁成功。
  • 多核: 见上面例子。
    那么怎么解决呢? 能不能让硬件做一种加锁的原子操作呢? 大名鼎鼎的“test and set”指令就是做这个事情的,该指令将读取内存、判断和设置值作为一个原子操作。单核环境下,锁的操作肯定是原子性了,多核呢?貌似还是不行,因为多个核心他们的锁操作是没有干扰的,都能够同时执行“test and set”,还是会出现两个线程同时获取到锁的情况, 所以硬件提供了锁内存总线的机制,在锁内存总线的状态下执行“test and set”操作就可以保证一个只有一个核执行成功,也就保证了不会存在多线程获取到锁的情况。

 

lock in OS

标签:release   you   表示   修改   过程   读取   空闲   ase   ==   

原文地址:https://www.cnblogs.com/xinfangzhang/p/12420108.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!