zoukankan      html  css  js  c++  java
  • C语言:线程同步之信号量(sem_init,sem_post,sem_wait)

    https://blog.csdn.net/houxiaoni01/article/details/103316566

    一、什么是信号量

    线程的信号量与进程间通信中使用的信号量的概念是一样,它是一种特殊的变量,它可以被增加或减少,但对其的关键访问被保证是原子操作。如果一个程序中有多个线程试图改变一个信号量的值,系统将保证所有的操作都将依次进行。

    而只有0和1两种取值的信号量叫做二进制信号量,在这里将重点介绍。而信号量一般常用于保护一段代码,使其每次只被一个执行线程运行。我们可以使用二进制信号量来完成这个工作。

    二、信号量的接口函数

    信号量的函数都以sem_开头,线程中使用的基本信号量函数有4个,它们都声明在头文件semaphore.h中。

    sem_init函数

    该函数用于创建信号量,其原型如下:

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

    该函数初始化由sem指向的信号对象,设置它的共享选项,并给它一个初始的整数值。
    pshared控制信号量的类型,如果其值为0,就表示这个信号量是当前进程的局部信号量,否则信号量就可以在多个进程之间共享,value为sem的初始值。调用成功时返回0,失败返回-1.

    sem_wait函数

    该函数用于以原子操作的方式将信号量的值减1。原子操作就是,如果两个线程企图同时给一个信号量加1或减1,它们之间不会互相干扰。它的原型如下:

    int sem_post(sem_t *sem);  
    
    • 1

    等待信号量,如果信号量的值大于0,将信号量的值减1,立即返回。如果信号量的值为0,则线程阻塞。相当于P操作。成功返回0,失败返回-1。sem指向的对象是由sem_init调用初始化的信号量。

    sem_post函数

    该函数用于以原子操作的方式将信号量的值加1。它的原型如下:

    int sem_post(sem_t *sem);  
    
    • 1

    释放信号量,让信号量的值加1。相当于V操作。与sem_wait一样,sem指向的对象是由sem_init调用初始化的信号量。调用成功时返回0,失败返回-1.

    sem_destroy函数

    该函数用于对用完的信号量的清理。它的原型如下:

    int sem_destroy(sem_t *sem);
    
    • 1

    成功时返回0,失败时返回-1.

    三、信号量的函数使用

    代码:

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <pthread.h>
    #include <semaphore.h>
    
      sem_t sem;
    
      void func1(void* arg)
      {
          sem_wait(&sem);
          int *running=arg;
          printf("thread running1
    ");
          printf("%d
    ",*running);
      }
    
      void func2(void* arg)
      {
          printf("pthread2 running
    ");
          sem_post(&sem);
      }
    
      int main()
      {
          sem_init(&sem,0,0);
          pthread_t thread[2];
          int a=5;
          pthread_create(&(thread[0]),NULL,(void*)func1,(void*)&a);
          printf("main thread running
    ");
          sleep(10);
          pthread_create(&(thread[1]),NULL,(void*)func2,(void*)&a);
          printf("main thread running2
    ");
          pthread_join(thread[0],NULL);
          pthread_join(thread[1],NULL);
          sem_destroy(&sem);
    
          return 0;
      }
    

    首先创建信号量,第二个参数为0,表示这个信号量是当前进程的局部信号量,初始值为0。

    然后使用pthread_create()函数创建两个线程,传入参数a。

    线程1创建完成后,由于信号量初始化value=0,调用sem_wait会阻塞这个线程,信号量的值将减少1(此时<0),这个线程函数就会等待。

    主线程sleep(10)后,线程2创建并执行调用,sem_post用于使信号量的值增加1,此时线程1可以执行。

    使用pthread_join等待所创建的两个线程的结束。

    编译:

     gcc testSem.c -o testSem -lpthread
     ./testSem 
    
    • 1
    • 2

    输出:

    main thread running
    main thread running2
    pthread2 running
    thread running1
    5
     
    有时候,不小心知道了一些事,才发现自己所在乎的事是那么可笑。
  • 相关阅读:
    陶瓷电容的结构、工艺、失效模式
    Vue.js最佳实践
    Vue 超快速学习
    CSS 小技巧
    HTML5 Canvas
    webkit下面的CSS设置滚动条
    Some untracked working tree files would be overwritten by checkout. Please move or remove them before you can checkout. View them
    JSCS: Please specify path to 'JSCS' package
    React中ref的使用方法
    React 60S倒计时
  • 原文地址:https://www.cnblogs.com/axjlxy/p/15288280.html
Copyright © 2011-2022 走看看