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

linux学习笔记(22)线程同步——线程信号量

线程信号量

线程信号量 vs 进程信号量

主要区别:

特性
进程信号量
线程信号量
头文件
#include
#include
创建
semget()
 + 复杂初始化
sem_init()
使用
semop()
sem_wait()
 / 
sem_post()
范围
系统范围
进程内部

线程信号量的三个核心函数

1. sem_init() - 初始化信号量

int sem_init(sem_t *sem, int pshared, unsigned int value);
  • sem: 信号量指针
  • pshared: 0表示线程间共享,非0表示进程间共享
  • value: 信号量初始值

2. sem_wait() - P操作(等待)

int sem_wait(sem_t *sem); // 阻塞等待 int sem_trywait(sem_t *sem); // 非阻塞尝试

3. sem_post() - V操作(释放)

int sem_post(sem_t *sem); // 释放信号量

简单的线程信号量例子

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
sem_t semaphore;  // 定义信号量
int shared_data = 0;
void* worker(void* arg) {int id = *(int*)arg;printf("线程%d: 等待信号量...\n", id);sem_wait(&semaphore);  // P操作printf("线程%d: 获得信号量,开始操作共享数据\n", id);shared_data++;sleep(2);  // 模拟工作printf("线程%d: 共享数据 = %d\n", id, shared_data);sem_post(&semaphore);  // V操作printf("线程%d: 释放信号量\n", id);return NULL;
}
int main() {pthread_t t1, t2;int id1 = 1, id2 = 2;// 初始化信号量,初始值为1(二进制信号量)sem_init(&semaphore, 0, 1);printf("创建两个线程...\n");pthread_create(&t1, NULL, worker, &id1);pthread_create(&t2, NULL, worker, &id2);pthread_join(t1, NULL);pthread_join(t2, NULL);printf("最终共享数据: %d\n", shared_data);// 销毁信号量sem_destroy(&semaphore);return 0;
}
创建两个线程...
线程1: 等待信号量...
线程1: 获得信号量,开始操作共享数据
线程2: 等待信号量...           ← 线程2在这里阻塞等待
线程1: 共享数据 = 1
线程1: 释放信号量
线程2: 获得信号量,开始操作共享数据
线程2: 共享数据 = 2
线程2: 释放信号量
最终共享数据: 2

生产者--消费者问题:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#define BUFFER_SIZE 5
int buffer[BUFFER_SIZE];
int in = 0, out = 0;
// 信号量定义
sem_t empty;    // 空槽位数量
sem_t full;     // 已使用槽位数量  
sem_t mutex;    // 二进制信号量,保护缓冲区
void* producer(void* arg) {int item = 0;while (1) {// 生产一个项目sleep(1);  // 模拟生产时间sem_wait(&empty);  // 等待空槽位sem_wait(&mutex);  // 进入临界区// 将项目放入缓冲区buffer[in] = item++;printf("生产者生产: %d, 位置: %d\n", buffer[in], in);in = (in + 1) % BUFFER_SIZE;        sem_post(&mutex);  // 离开临界区sem_post(&full);   // 增加已使用槽位}return NULL;
}
void* consumer(void* arg) {while (1) {sem_wait(&full);   // 等待有数据的槽位sem_wait(&mutex);  // 进入临界区// 从缓冲区取出项目int item = buffer[out];printf("消费者消费: %d, 位置: %d\n", item, out);out = (out + 1) % BUFFER_SIZE;sem_post(&mutex);  // 离开临界区sem_post(&empty);  // 增加空槽位sleep(2);  // 模拟消费时间}return NULL;
}int main() {// 初始化信号量sem_init(&empty, 0, BUFFER_SIZE);  // 初始有5个空位sem_init(&full, 0, 0);             // 初始没有数据sem_init(&mutex, 0, 1);            // 二进制信号量pthread_t prod, cons;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);sem_destroy(&mutex);return 0;
}

http://www.dtcms.com/a/460973.html

相关文章:

  • 如何用营销自动化提升开信率与转化率
  • 人形机器人安全研究
  • 比斯特自动化|为什么焊接18650电池离不开点焊机?
  • 多字节串口收发IP设计(二)串口通信扫盲
  • 人工智能基础知识笔记十七:微调方法
  • 北京企业免费建站农八师建设兵团社保网站
  • 《强化学习数学原理》学习笔记11——阶段策略迭代算法
  • Qt QtConcurrent使用入门浅解
  • C语言字符串与内存操作函数完全指南
  • 【第五章:计算机视觉-项目实战之生成式算法实战:扩散模型】2.CV黑科技:生成式算法理论-(5)Stable Diffusion模型讲解
  • Cookie和Seeion在客户端和服务端的角色作用
  • Linux 远程Ubuntu服务器本地部署大模型 EmoLLM 中常见的问题及解决方案 万字详解
  • 如何建设公司网站信息灯塔网站seo
  • Java 中 `equals()`、`==` 和 `hashCode()` 的区别
  • 成像系统(十四-1:《工业级ISP流水线:ISP前端处理 - 从原始数据到可用图像》):从LED冬奥会、奥运会及春晚等大屏,到手机小屏,快来挖一挖里面都有什么
  • vue-router(vue 路由)基本使用指南(二)
  • 深入理解 Java中的 异常和泛型(指南十二)
  • 草莓植物(plant)【高精度-->array高级!!!】
  • 3D 图表、堆叠饼图为什么是灾难?
  • Nacos 全解析:从注册中心到配置管理的实战指南
  • 微信小程序开发从零基础到项目发布的全流程实战教程(四)
  • wordpress 全站静态二次开发小程序
  • linux命令--后端项目部署
  • 网页版云手机 梦幻西游手游
  • HTML5 与 HTTPS,页面能力、必要性、常见问题与实战排查
  • 网站检索功能怎么做建设宣传网站的必要性
  • 做网站维护需要懂什么网站建设洽谈问题
  • 17、Linux 文件压缩与解压
  • IDEA编译时报错OOM的解决方案
  • .NET驾驭Word之力:基于规则自动生成及排版Word文档