关键词搜索

源码搜索 ×
×

C 语言编程 — semaphore 信号量操作

发布2023-03-15浏览537次

详情内容

目录

信号量

信号量(semaphore)是一种常被用于多线程或多进程场景中的同步机制,用于保证多线程或多进程对共享数据的读/写操作是顺序的。

信号量的本质上是一个计数器,维护着一个 Value:

  • 当 value > 0 时,信号量表示有可用的资源。
  • 当 value < 0 时,信号量表示所有的资源都已经被占用了。

二元信号量

二元信号量(Binary Semaphore),即:计数器维护的 Value 只有 0 和 1 着两种可能,以此来实现互斥,所以也称为互斥信号量。

  • 1:表示可以访问资源。
  • 0:表示不能访问资源。

需要注意的是,二元信号量只能用于实现互斥,无法实现同步。如果需要实现线程间的同步,可以使用计数信号量(Counting Semaphore)。

另外,二元信号量的使用应尽量避免死锁问题的发生,即:避免出现多个线程相互等待的情况。

semaphore.h 库

C 语言可以使用 semaphore.h 库来使用二元信号量。

sem_init()

函数作用:用于创建并初始化一个二元信号量实体。

函数原型

  • sem 参数:指向一个信号量实体。
  • pshared 参数:是一个类型标志位。
    • 0:表示信号量是在多线程间共享的;
    • non-0:表示信号量是在多进程间共享的。
  • value 参数:表示信号量的初始值,只能为 0 或 1。
#include <semaphore.h>

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

    sem_wait()

    函数作用

    • 如果二元信号量的 Value 为 0,那么 sem_wait() 会将 Caller(调用者)阻塞,等待 Value 变 1 为止。
    • 如果 Value 为 1,那么 sem_wait() 会将其减 1 并返回 0,表示自己拿到了信号;

    函数原型

    • sem 参数:指向一个信号量实体。
    #include <semaphore.h>
    
    int sem_wait(sem_t *sem);
    

      sem_post()

      函数作用:当线程完成了共享数据的访问后,应该使用 sem_post() 释放二元信号量,即:将 Value 变 1,让其他线程可以获取。

      函数原型

      • sem 参数:指向一个信号量实体。
      #include <semaphore.h>
      
      int sem_post(sem_t *sem);
      

        示例程序

        #include <stdio.h>
        #include <stdlib.h>
        #include <pthread.h>
        #include <semaphore.h>
        
        #define NUM_THREADS 2
        
        sem_t mutex;
        
        void* thread_func(void* arg) {
            int tid = *(int*) arg;
            printf("Thread %d waiting...\n", tid);
        
        	/* 用一个互斥信号量来保护一个临界区。 */
            sem_wait(&mutex);  // 每个线程都先等待信号量变为正,然后进入临界区进行操作。
            printf("Thread %d entered critical section.\n", tid);
            sleep(1);
            printf("Thread %d exiting critical section.\n", tid);
            sem_post(&mutex);  // 离开临界区并释放信号量。
        
            pthread_exit(NULL);
        }
        
        int main() {
            pthread_t threads[NUM_THREADS];
            int thread_args[NUM_THREADS];
            int i;
        
            // Initialize the semaphore
            sem_init(&mutex, 0, 1);
        
            // Create the threads
            for (i = 0; i < NUM_THREADS; i++) {
                thread_args[i] = i;
                pthread_create(&threads[i], NULL, thread_func, &thread_args[i]);
            }
        
            // Wait for the threads to finish
            for (i = 0; i < NUM_THREADS; i++) {
                pthread_join(threads[i], NULL);
            }
        
            // Destroy the semaphore
            sem_destroy(&mutex);
        
            return 0;
        }
        
          4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47

        相关技术文章

        点击QQ咨询
        开通会员
        返回顶部
        ×
        微信扫码支付
        微信扫码支付
        确定支付下载
        请使用微信描二维码支付
        ×

        提示信息

        ×

        选择支付方式

        • 微信支付
        • 支付宝付款
        确定支付下载