信号量与自旋锁的比较

时间:2021-10-29 14:44:54
sem就是一个睡眠锁.如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。这时处理器获得*去执行其它代码。当持有信号量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而便可以获得这个信号量。信号量一般在用进程上下文中.它是为了防止多进程同时访问一个共享资源(临界区).

spin_lock叫自旋锁.就是当试图请求一个已经被持有的自旋锁.这个任务就会一直进行 忙循环——旋转——等待,直到锁重新可用(它会一直这样,不释放CPU,它只能用在短时间加锁).它是为了防止多个CPU同时访问一个共享资源(临界区).它一般用在中断上下文中,因为中断上下文不能被中断,也不能被调度.


自旋锁对信号量

需求              建议的加锁方法

低开销加锁           优先使用自旋锁

短期锁定            优先使用自旋锁

长期加锁            优先使用信号量

中断上下文中加锁        使用自旋锁

持有锁是需要睡眠、调度     使用信号量 


进程间的sem.线程间的sem与内核中的sem的功能就很类似.

进程间的sem,线程间的sem功能是一样的.只是线程的sem,它在同一个进程空间,他的初始化,使用更方便.

进程间的sem,就是进程间通信的一部分,使用semget,semop等系统调用来完成.

内核中的sem 被锁定,就等于被调用的进程占有了这个sem.其它进程就只能进行睡眠队列.这与进程间的sem基本一致.


区别

Spin_lock

semaphore

保护的对象

一段代码

一个设备(必要性不强),

一个变量,

一段代码

保护区可被抢占

不可以

可以。

可允许在保护对象(代码)中休眠

不可以

可以。但最好不这样。

保护区能否被中断打断

可以,这样容易引发死锁。

最好是关了中断再使用此锁。

因为有可能中断处理例程也需要得到同一个锁。

可以。

其它功能

 

可完成同步,有传达信息的能力。

     

试图占用锁不成功后,进程的表现

不放开CPU,自己自旋。

进入一个等待队列。

释放锁后,还有其它进程等待时,内核如何处理

哪个进程得到运行的权力,它就得到了锁。

从等待队列中选一个出来占用此sem.

内核对使用者的要求

被保护的代码执行时间要短,是原子的,

不能主动的休眠。

不能调用有可以休眠的内核函数。

 

风险

发生死锁

 
 

不允许锁的持有者二次请求同一个锁。

不允许锁的持有者二次请求同一个锁。

信号量在生产者与消费者模式中可以进行同步。

当sem的down和UP分别出现在对立函数中(读,写函数),其实这就是在传达一种信息。表示当前是否有数据可读的信息。

read_somthing()

{

     down(设备)   占用了此设备          此时没有其它人都使用此设备上的所有操作(函数)

     if(有数据)

    {

       读完它。

          ()

    }

    else

     {

              up(设备)

              down(有数据的sem)sem=1表示有数据,为0表示无数据。

      }

}

write_somthing()

{

     down(设备)   占用了此设备          此时没有其它人都使用此设备上的所有操作(函数)

     if(有数据)

    {

          不写。

          up(设备)

          return

    }

    else

     {

              写入数据

              up(有数据的sem)sem=1表示有数据,为0表示无数据。

             up(设备)

            return;

      }

}