我正在学习Linux系统编程,所以我只是尝试编写一个非常普通的程序,即生产者和使用者。我使用信号量机制来实现我的代码。不幸的是,我遇到了分段错误,但我确实找不到我哪里错了。希望有人能帮助我,谢谢。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <semaphore.h>
sem_t sem_consumer;
sem_t sem_producer;
typedef struct node
{
int data;
struct node *next;
} Node;
Node * head = NULL;
void * producer(void *arg)
{
while (1)
{
sem_wait(&sem_producer);
Node *ptr = (Node *)malloc(sizeof(Node));
ptr->data = rand() % 1000;
printf("++++++ producer: %lu, %d\n", pthread_self(), ptr->data);
ptr->next = head;
head = ptr;
sem_post(&sem_consumer);
}
return NULL;
}
void * consumer(void * arg)
{
while (1)
{
sem_wait(&sem_consumer);
Node *pdel = head;
head = head -> next;
printf("------ consumer: %lu, %d\n", pthread_self(), pdel->data);
free(pdel);
sem_post(&sem_producer);
}
return NULL;
}
int main(int argc, char *argv[])
{
sem_init(&sem_consumer, 0, 0);
sem_init(&sem_producer, 0, 3);
pthread_t pthid[2];
pthread_create(&pthid[0], NULL, producer, NULL);
pthread_create(&pthid[1], NULL, consumer, NULL);
for (int i = 0; i < 2; i++)
{
pthread_join(pthid[i], NULL);
}
sem_destroy(&sem_consumer);
sem_destroy(&sem_producer);
return 0;
}
答案 0 :(得分:2)
此
sem_init(&sem_producer, 0, 3);
将sem_producer
信号量初始化为3,从而允许生产者线程和消费者线程同时访问
ptr->next = head;
head = ptr;
和
Node *pdel = head;
head = head -> next;
printf("------ consumer: %lu, %d\n", pthread_self(), pdel->data);
free(pdel);
您的链表没有受到信号灯的正确保护。那是比赛条件。
将sem_producer
初始化为1将纠正竞态条件:
sem_init(&sem_producer, 0, 1);
我可能还没有发现其他错误。
答案 1 :(得分:2)
我认为主要问题是:
head
sem_producer
和sem_consumer
信号量用于表示“ 您可以拿东西”或“ 您可以拿东西”来控制资源的使用-例如,如果要确保列表的深度永远不会超过三个对象。当生产者/使用者线程具有不同的执行时间时,这一点尤其重要。如果您对生产消费者可能永远无法跟上的物品负荷不太感兴趣,那么可以完全删除sem_producer
。
Mutexes(“ 互斥”)用于确保两个线程不会同时处理一个对象。我建议您在信号量旁边的指针操作周围使用互斥体。
pthread_mutex_t mux;
void *producer(void *arg) {
while (1) {
sem_wait(&sem_producer);
/* gather data */
pthread_mutex_lock(&mux);
p_new->next = head;
head = p_new;
pthread_mutex_unlock(&mux);
sem_post(&sem_consumer);
}
return NULL;
}
void *consumer(void *arg) {
while (1) {
sem_wait(&sem_consumer);
pthread_mutex_lock(&mux);
p_next = head;
if (p_next != NULL) {
head = p_next->next;
}
pthread_mutex_unlock(&mux);
/* skip if there isn't actually a new item */
if (p_next != NULL) {
/* do processing and discard */
}
sem_post(&sem_producer);
}
return NULL;
}
别忘了给pthread_mutex_init()
和pthread_mutex_destroy()
打电话。