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

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

 

以上是关于lock in OS的主要内容,如果未能解决你的问题,请参考以下文章

python--登陆接口

Java多线程——Lock&Condition

一旦单击带有 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?)(代码片段