linux系统使用POSIX信号量实现多线程同步sem_init sem_wait sem_post sem_destroy

2024-01-02 18:54:30

POSIX 信号量

定义

  • POSIX 信号量(POSIX semaphores)是一种在多线程和多进程编程中用于同步和互斥的机制。它是 POSIX 标准中定义的一组函数和数据结构,用于实现线程或进程之间的同步。
  • 信号量是一个计数器,用于控制对共享资源的访问。它可以用来解决多个线程或进程之间的竞争条件和互斥访问问题。

主要特点

  • 计数器:信号量包含一个整数计数器,它可以是任何非负整数。
  • 等待和通知:线程或进程可以等待信号量的值达到某个条件,然后被通知继续执行。
  • 原子操作:对于每个信号量操作(如等待和通知),POSIX 信号量提供了原子操作的保证,确保线程或进程之间的同步和互斥。

主要函数

  • sem_init:用于初始化信号量。
  • sem_wait:用于等待信号量,如果信号量的值大于 0,则将其减一;如果信号量的值为 0,则线程或进程将被阻塞,直到信号量的值变为大于 0。
  • sem_post:用于释放信号量,将其值加一。如果有其他线程或进程正在等待这个信号量,它们将有机会继续执行。
  • sem_destroy:用于销毁信号量。
    POSIX 信号量可以在多种操作系统上使用,并且是跨平台的同步机制之一。它提供了一种可靠且功能强大的方式来管理线程或进程之间的同步和互斥访问,以确保共享资源的正确使用和避免竞态条件。

例程

参考

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

sem_t semProducer;
sem_t semCustomer;

typedef struct node  //节点结构
{
    int data;
    struct node* next;
} Node;

Node* g_head =  nullptr;  //永远指向链表头部的指针

void* funProducer(void* arg);  //生产者--添加一个头结点
void* funCustomer(void* arg);  //消费者--删除一个头结点

int main(int argc, char *argv[])
{
    pthread_t p1;
    pthread_t p2;

    sem_init(&semProducer, 0, 4);  //初始化生产者线程信号量, (赋予 4 个,对比下一行,让生产者先运行)
    sem_init(&semCustomer, 0, 0);  //初始化消费者线程信号量, (赋予 0 个, 一开始就让消费者处于阻塞状态)

    pthread_create(&p1, nullptr, funProducer, nullptr);  //创建生产者线程
    pthread_create(&p2, nullptr, funCustomer, nullptr);  //创建消费者线程

    pthread_join(p1, nullptr);  //阻塞回收子线程
    pthread_join(p2, nullptr);

    sem_destroy(&semProducer);  //销毁生产者信号量
    sem_destroy(&semCustomer);  //销毁消费者信号量

    return 0;
}

void* funProducer(void* arg)
{
    while (true) {
        sem_wait(&semProducer);  //semProducer--,  == 0, 则阻塞
        Node* pNew = new Node();
        pNew->data = rand() % 1000; 
        pNew->next = g_head;
        g_head = pNew;
        printf("-----funProducer(生产者): %lu, %d\n", pthread_self(), pNew->data);
        sem_post(&semCustomer); // semCustomer++

        sleep(rand() % 3);  //随机休息 0~2 s
    }
    
    return nullptr;
}

void* funCustomer(void* arg)
{
    while (true) {
        sem_wait(&semCustomer);  //semCustomer--,  == 0, 则阻塞
        Node* pDel = g_head;
        g_head = g_head->next;
        printf("-----funCustomer(消费者): %lu, %d\n", pthread_self(), pDel->data);
        delete pDel;
        sem_post(&semProducer); // semProducer++
    }

    return nullptr;
}

运行结果
在这里插入图片描述

文章来源:https://blog.csdn.net/qq_40234695/article/details/135346478
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。