跳转到主内容
思享编程网:思考分享,玩转编程世界!

Linux下信号量怎么用?sem_wait()函数详解!

文章导读

大家好,我是陆砚码。今天我们来聊聊Linux下的信号量,也就是我们常说的信号灯。信号量是互斥锁的升级版,它能更好地控制多个线程对共享资源的访问。这篇文章会通过一个“生产者-消费者”的例子,手把手教你如何使用信号量和sem_wait()函数。

信号量(信号灯)的理解和使用

信号量可以简单理解为多个互斥量的集合,是加强版的互斥锁。它的使用步骤和互斥量很像,只是头文件改为了

#include 

使用步骤

  • sem_t sem;
    :定义变量
  • int sem_init(sem_t *sem, int pshared, unsigned int value);
    :初始化信号量
  • int sem_wait(sem_t *sem);
    :加锁
  • int sem_post(sem_t *sem);
    :解锁
  • int sem_destroy(sem_t *sem);
    :销毁信号量

“生产者-消费者”例子

这里我们通过一个“生产者-消费者”的例子来演示信号量的使用。生产者负责生产数据,消费者负责消费数据。通过信号量来控制生产者和消费者对共享资源的访问。

代码实现

#include 
#include 
#include 
#include 
#include 

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
", 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
", pthread_self(), pDel->data);
        delete pDel;
        sem_post(&semProducer); // semProducer++
    }

    return nullptr;
}

小结与拓展

信号量是Linux下多线程编程中非常重要的一个概念,它能有效地控制多个线程对共享资源的访问。通过本文的讲解,相信大家对信号量和sem_wait()函数有了更深入的理解。如果你对Linux多线程编程还有其他疑问,欢迎访问思享编程网(www.sxgpb.com)了解更多内容。

我是陆砚码,思享编程网资深编辑,热爱技术分享,期待与你在网站上交流学习。

相关文章