当前位置: 首页 > article >正文

C语言中信号量:<semaphore.h>头文件

<semaphore.h> 是一个 POSIX 标准定义的头文件,用于提供信号量(semaphore)的接口。信号量是用于线程或进程间同步的一种机制,可以控制访问共享资源的线程数目,广泛应用于多线程和多进程编程。

本文将详细介绍 <semaphore.h> 的数据类型、函数、以及示例。


1. 引入头文件

在使用信号量功能时,必须包含 <semaphore.h>

#include <semaphore.h>

2. 数据类型

sem_t

  • 信号量的主要数据类型。
  • 定义为一个结构体,用于存储信号量的当前值和相关信息。
  • 可以用于进程间或线程间的同步。

3. 函数及用途

以下是 <semaphore.h> 中的主要函数:

(1) 初始化与销毁信号量

函数描述
int sem_init(sem_t *sem, int pshared, unsigned int value);初始化一个信号量。
int sem_destroy(sem_t *sem);销毁一个信号量。
  • sem_init 参数说明
    • sem:指向信号量的指针。
    • pshared
      • 如果为 0,信号量用于线程间同步。
      • 如果为非 0,信号量用于进程间同步(需要位于共享内存中)。
    • value:信号量的初始值(代表资源数目)。
  • 返回值:成功返回 0,失败返回 -1

(2) 信号量操作

函数描述
int sem_wait(sem_t *sem);将信号量的值减 1。如果信号量值为 0,则阻塞直到信号量值大于 0。
int sem_trywait(sem_t *sem);尝试将信号量值减 1。如果信号量值为 0,不阻塞,返回错误。
int sem_post(sem_t *sem);将信号量的值加 1。如果有阻塞的线程,唤醒其中一个线程。
int sem_getvalue(sem_t *sem, int *sval);获取信号量的当前值。

4. 示例

(1) 线程间的同步

以下是一个简单的生产者-消费者问题示例,演示如何使用信号量控制线程同步:

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

#define BUFFER_SIZE 5

int buffer[BUFFER_SIZE];
int count = 0;

sem_t empty;  // 表示空位的信号量
sem_t full;   // 表示已占用位的信号量
pthread_mutex_t mutex;  // 保护共享资源的互斥锁

void *producer(void *arg) {
    for (int i = 0; i < 10; i++) {
        sem_wait(&empty);             // 减少空位
        pthread_mutex_lock(&mutex);   // 进入临界区

        buffer[count++] = i;          // 放入数据
        printf("Produced: %d\n", i);

        pthread_mutex_unlock(&mutex); // 离开临界区
        sem_post(&full);              // 增加已占用位
        sleep(1);
    }
    return NULL;
}

void *consumer(void *arg) {
    for (int i = 0; i < 10; i++) {
        sem_wait(&full);              // 减少已占用位
        pthread_mutex_lock(&mutex);   // 进入临界区

        int item = buffer[--count];   // 取出数据
        printf("Consumed: %d\n", item);

        pthread_mutex_unlock(&mutex); // 离开临界区
        sem_post(&empty);             // 增加空位
        sleep(2);
    }
    return NULL;
}

int main() {
    pthread_t prod, cons;

    sem_init(&empty, 0, BUFFER_SIZE); // 初始化空位信号量
    sem_init(&full, 0, 0);            // 初始化已占用信号量
    pthread_mutex_init(&mutex, NULL); // 初始化互斥锁

    pthread_create(&prod, NULL, producer, NULL);
    pthread_create(&cons, NULL, consumer, NULL);

    pthread_join(prod, NULL);
    pthread_join(cons, NULL);

    sem_destroy(&empty);              // 销毁信号量
    sem_destroy(&full);
    pthread_mutex_destroy(&mutex);    // 销毁互斥锁

    return 0;
}
输出示例
Produced: 0
Consumed: 0
Produced: 1
Produced: 2
Consumed: 1
Consumed: 2
...

(2) 进程间的同步

信号量也可以在进程间共享,但需要设置 sem_initpshared 参数为非 0,并将信号量存储在共享内存中。


5. 注意事项

  1. 线程间 vs 进程间信号量

    • pshared 为 0 时,信号量用于线程间同步。
    • 为非 0 时,需要将信号量置于共享内存区域,用于进程间同步。
  2. 阻塞与非阻塞操作

    • sem_wait 会阻塞直到信号量值大于 0。
    • sem_trywait 不会阻塞,而是立即返回成功或失败。
  3. 信号量的销毁

    • 在不再需要信号量时,必须调用 sem_destroy 释放资源。
  4. 避免死锁

    • 正确管理信号量和互斥锁的顺序,以避免线程或进程死锁。

6. 总结

<semaphore.h> 提供了信号量相关的功能,适用于多线程或多进程场景下的同步问题。通过使用 sem_t 数据类型及相关函数,开发者可以有效地控制对共享资源的访问,确保线程安全。


http://www.kler.cn/a/443013.html

相关文章:

  • 常见的http状态码 + ResponseEntity
  • 如何评价deepseek-V3 VS OpenAI o1 自然语言处理成Sql的能力
  • Mysql进阶篇
  • Java参数值传递
  • Linux内核TTY子系统有什么(6)
  • 六、Angular 发送请求/ HttpClient 模块
  • 2024年12月18日Github流行趋势
  • vue3渲染el-tree组件,给默认选中的节点,禁用所有子节点
  • C# 实现 WinForm 全屏置顶
  • systemverilog中的循环(loop)
  • 批量DWG文件转换低版本(CAD图转低版本)——c#插件实现
  • TCP 三次握手四次挥手
  • Jmeter的性能测试
  • 汽车供应链 “剧变”开始,“智能感知潜在龙头”诞生
  • 自己构建的python如何可以通过 PyPI安装
  • 【多模态】swift框架使用qwen2-vl
  • C# OpenCvSharp DNN 实现百度网盘AI大赛-表格检测第2名方案第一部分-表格边界框检测
  • 网络协议详解---TCP、HTTP、WebSocket、socket、轮询等
  • Unity3D Shader实现黑洞效果详解
  • AI 语言模型产业的投资困境与发展困境分析
  • 细说STM32F407单片机SPI基础知识
  • 【HAL库】STM32CubeMX开发----STM32F407----Time定时器中断实验
  • Ubuntu 配置静态 IP 地址
  • Excel工作表不能相互移动和复制?有何解决方法?
  • 【系统架构设计师】真题论文: 论软件设计方法及其应用(包括解题思路和素材)
  • 神州数码DCME-320 online_list.php存在任意文件读取漏洞