使用信号量来实现资源的计数,使得生产者和消费者之间的活动能够有序进行。详见代码注释
code:
/*
#include <semaphore.h>
信号的类型 sem_t
int sem_init(sem_t *sem, int pshared, unsigned int value);
-初始化信号量
- 参数:
-sem :就是信号量
-pshared :0用在线程间;非0的话用在进程间
-value :用来记录信号量中的值
int sem_destroy(sem_t *sem);
- 释放资源
int sem_wait(sem_t *sem);
- 对信号量加锁,对信号量的值减1,为零的话就阻塞
int sem_trywait(sem_t *sem);
int sem_timewait(sem_t *sem, const struct timespec *abs_timeout);
int sem_post(sem_t *sem);
- 解锁, 调用一次就加1,会唤醒阻塞的
int sem_getvalue(sem_t *sem, int *sval);
sem_t psem;
sem_t csem;
init(psem, 0, 8);
init(csem, 0, 0);
producer(){
sem_wait(&psem);
sem_post(&csem);
}
customer(){
sem_wait(&csem);
sem_post(&psem);
}
*/
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
//创建一个互斥量
pthread_mutex_t mutex;
//创建两个信号量
sem_t psem, csem;
struct Node
{
int num;
struct Node* next;
};
//头结点
struct Node* head = NULL;
void * producer(void* arg){
//不断创建新节点添加到链表中,头插
while (1)
{
sem_wait(&psem);
pthread_mutex_lock(&mutex);
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->next = head;
head = newNode;
newNode->num = rand() % 1000;
printf("add node, num : %d, tid : %ld\n", newNode->num, pthread_self());
pthread_mutex_unlock(&mutex);
sem_post(&csem); //表示消费者有一个可以消费
usleep(100);
}
return NULL;
}
void * customer(void* arg){
while (1)
{
sem_wait(&csem);
pthread_mutex_lock(&mutex);
struct Node* temp = head;
head = head->next;
printf("del node , num : %d, tid : %ld\n",temp->num, pthread_self());
free(temp);
pthread_mutex_unlock(&mutex);
sem_post(&psem);//通知生产者有一个空位需要生产了
}
return NULL;
}
int main(){
pthread_mutex_init(&mutex, NULL);
sem_init(&psem,0,8);
sem_init(&csem,0,0);
//创建5个生产者线程,5个消费者线程,用链表来作为容器(添加数据采用头插法)
pthread_t ptids[5], ctids[5];
for(int i = 0; i < 5; ++i){
pthread_create(&ptids[i], NULL, producer, NULL);
pthread_create(&ctids[i], NULL, customer, NULL);
}
for(int i = 0; i < 5; ++i){
pthread_detach(ptids[i]);
pthread_detach(ctids[i]);
}
while (1)
{
sleep(10);
}
pthread_mutex_destroy(&mutex);//这个地方不能立马销毁
pthread_exit(NULL);//退出子线程
return 0;
}