• 信号量整理


    信号量

    一、

    1、信号量的数据类型为结构sem_t,它本质上是一个长整型的数。

    2、例如:

    typedef   struct
    {
        struct   _pthread_fastlock   __sem_lock;
        int   __sem_value;
        _pthread_descr   __sem_waiting;
    }   sem_t;

    3、sem_t分为有名和无名。有名的sem_t通过sem_open来创建用于进程通信;而无名的sem_t通过sem_init的初始化是基于内存的信号量

    4、有名和无名的sem_t主要区别:

    1)效率:有名sem_t是放在文件,无名的sem_t是放在内存。

    2)限制:有名的sem_t可以用来同步多线程,任意多进程。而无名的sem_t可以用来同步多线程,以及Fork出来的进程间的同步。

    (如果没有放到共享内存,就算将pshared设置为1,也起不了作用。

    3)pshared传递一个非零将会使函数调用失败,属于无名信号量。

    二、

    1、sem_init:用来初始化一个信号量。

    1、int sem_init(sem_t *sem, int pshared, unsigned int value);

    1)sem_init函数是Posix信号量操作中的函数,作用是对由sem指定的信号量进行初始化。sem_init() 初始化一个定位在 sem 的匿名信号量。

    2)sem为指向信号量结构的一个指针,指向信号量对象。

    3)value 参数指定信号量(sem)的初始值。value给出了信号量的初始值。指定信号量值的大小。一般为0或者1。

    4)pshared 参数指明信号量的类型,即信号量是由进程内线程共享,还是由进程之间共享。如果 pshared 的值为 0,只能为当前进程的所有线程共享,并且应该放置在这个进程的所有线程都可见的地址上(如全局变量,或者堆上动态分配的变量)。pshared不为0时,其它进程就能够共享这个信号量。

    5)sem_init()该函数调用成功返回0,失败返回-1。 

    2、补充:
    pshared传递一个非零将会使函数调用失败。 

    2、sem_post:

    1、int sem_post(sem_t *sem);用来增加信号量的值。

    2、 sem_post函数的作用是给信号量的值加上一个“1”,它是一个“原子操作”即同时对同一个信号量做加“1”操作的两个线程是不会冲突的,而同时对同一个文件进行读、加和写操作的两个程序就有可能会引起冲突,信号量的值永远会正确地加一个“2”--因为有两个线程试图改变它。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。释放信号量,让信号量的值加1。相当于V操作。 

    3、sem_wait:

    1、int sem_wait(sem_t * sem);被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。等待信号量,如果信号量的值大于0,将信号量的值减1,立即返回。如果信号量的值为0,则线程阻塞。相当于P操作。成功返回0,失败返回-1。

    2、sem_wait函数也是一个原子操作,它的作用是从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值才开始做减法,即如果你对一个值为2的信号量调用sem_wait(),线程将会继续执行,信号量的值将减到1。如果对一个值为0的信号量调用sem_wait(),这个函数就会原地等待直到有其它线程增加了这个值使它不再是0为止。如果有两个线程都在sem_wait()中等待同一个信号量变成非零值,那么当它被第三个线程增加 一个“1”时,等待线程中只有一个能够对信号量做减法并继续执行,另一个还将处于等待状态。

    例如:

    sem_init(&svs.useFlag, 0, 1);       //初始化信号量,同一个进程中线程共享,并且赋值为1。

    sem_wait(&svs.useFlag);         // 锁定svs数据,以免在创建的新线程使用前被修改,信号量减一。

    sem_post(&svs.useFlag);        //信号量加1。

    sem_post(&svs->useFlag);        //信号量加1。
       4、sem_trywait 

    1、sem_trywait ( sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。

    2、信号量这种“只用一个函数就能原子化地测试和设置”的能力下正是它的价值所在。还有另外一个信号量函数sem_trywait,它是sem_wait的非阻塞搭档。
    5、sem_destroy

    1、sem_destroy(sem_t *sem)用来释放信号量sem。其中sem是要销毁的信号量。只有用sem_init初始化的信号量才能用sem_destroy销毁。这个函数的作用是在我们用完信号量对它进行清理。下面的定义:
       #include<semaphore.h>
       int sem_destroy (sem_t *sem);
        这个函数也使用一个信号量指针做参数,归还自己占据的一切资源。在清理信号量的时候如果还有线程在等待它,用户就会收到一个错误。与其它的函数一样,这些函数在成功时都返回“0”。

    信号量的使用如下步骤小结:
     1.声明信号量sem_t sem1;
     2.初始化信号量sem_init(&sem1,0,1); /
     3.sem_post和sem_wait函数配合使用来达到线程同步
     4.释放信号量int sem_destroy (sem_t *sem1);

  • 相关阅读:
    numpy库:常用基本
    高考的结束,新的开始
    Hello World!
    第一篇随笔
    Linux命令之文件与用户权限
    看山不是山,看水不是水
    Python基础篇【第1篇】: Python基础
    css居中
    JS正则表达式(一)
    小问题总结
  • 原文地址:https://www.cnblogs.com/L-102/p/11437986.html
Copyright © 2020-2023  润新知