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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值