一点点对semaphore的理解

semaphore 在UNIX系统中是信号量的意思,通常在并发的访问共享资源的时候会用到。并发进程为了访问共享资源,通常会经过如下步骤:

  1. 测试控制该共享资源的信号的值。
  2. 如果该信号量值为正,则表示该进程可以使用该资源。这种情况下,该进程会将信号量的值+1处理,表明该已经已经被一个进程使用。
  3. 反之如果信号量的值为0,则表示当前进程无法使用该资源。那么该进程就进入sleep状态直到控制该资源的信号量的值变成正数。当该经常从sleep被唤醒的时候,会跳到步骤1,尝试重新测试信号量的值。

当一个拥有共享资源的进程处理完他的业务逻辑之后,该共享资源的信号量的值会+1,表明当前这个共享资源再次可用。如果有其他进程需要改共享资源并且处于睡眠状态,此时该进程会被唤醒。
测试信号量值和将信号量的值--的操作必须是一个原子性的操作,这个操作是有操作系统内核实现的。 通常情况下,控制着单个资源的信号量会初始化为1. 信号量在内核中的结构如下

struct semid_ds {
    unsigned short semval;      // semaphore value, always >= 0 
    pid_t   sempid;             // pid for last operation
    unsigned short semncnt;     // processes awaiting semval>curval
    unsigned short semzcnt;     // proceses awaiting semval == 0
}

总的来说,就是当信号量值>0,表示可用。但值==0,则不可用,且进程会阻塞进入睡眠状态,但信号量再次可用的时候,阻塞的进程会被唤起重新去获取信号量值。

go语言的Mutex就是基于信号量实现的。不同点是go的协程在首次获取锁失败的时候,不会立即阻塞并睡眠,而是会自旋几次尝试再次获取锁,如果超过的尝试次数还是获取失败,则进入阻塞状态。

Leave a Comment

Your email address will not be published. Required fields are marked *

PHP 8.1.1 - 19.184 ms, 0 Q