文章导读
大家好,我是陆砚码。今天我们来聊聊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)了解更多内容。
