生产者-消费者在C中使用信号量 [英] Producer-consumer using semaphore in C

查看:102
本文介绍了生产者-消费者在C中使用信号量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用信号量编写生产者-消费者问题.在下面的代码中,存在创建使用者时同步执行的问题.对于它的解决方案,在使用者的切换块中添加了sleep语句.
请为我提供高效的同步解决方案.任何有关代码改进的建议都是很有帮助的.

There is producer-consumer problem is written using semaphore. In below code, there is an issue of synchronization execution while the consumer is created. And for its solution, sleep statement is added in switch block of the consumer.
Kindly help me with the efficient solution for the synchronization. Any suggestion for the improvement of code is really helpful.

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<semaphore.h> /* sem_t */
#include<stdlib.h>

#define BUF_SIZE 2

struct buffer {
        int data;
};

struct buffer buf[BUF_SIZE];

sem_t fill, empty;

int value, i;

void *producer(void *data);
void *consumer(void *data);

int main(void)
{
    int sel, prod_data, cons_data;
    int k;

    if (sem_init(&empty, 0, BUF_SIZE)) {
        printf("Error: semaphore not initialize\n");
        return -1;
    }
    if (sem_init(&fill, 0, 0)) {
        printf("Error: semaphore not initialize\n");
        return -1;
    }

    while (1) {
        printf(".........................................................\n");
        printf("Selection\n");
        printf("Producer : 1 | Consumer : 2 | Display : 3 | Exit : 0 || ");
        scanf("%d",&sel);
        printf(".........................................................\n");

        switch (sel) {
        case 1:
            sem_getvalue(&empty, &value);
//          printf("Prod_e: %d\n", value);
            sem_getvalue(&fill, &value);
//          printf("Prod_f: %d\n", value);
            printf("\nProducer\n");
            pthread_t prod_t;
            printf("Enter data:");
            scanf("%d", &prod_data);
            if (pthread_create(&prod_t, NULL, producer, (void *) &prod_data)) {
                printf("Error: thread not created\n");
                return -1;
            }
            break;
        case 2:
            printf("\nConsumer\n");
            sem_getvalue(&empty, &value);
//          printf("Cons_e: %d\n", value);
            sem_getvalue(&fill, &value);
//          printf("Cons_f: %d\n", value);
            pthread_t con_t;
            if (pthread_create(&con_t, NULL, consumer, (void *) &cons_data)) {
                printf("Error: thread not created\n");
                return -1;
            }
            if (i == 0) {
                printf("Buffer empty\n");
                break;
            }
//              sleep(1); // if commented then synchronization issue
            printf("Consume data: %d\n", cons_data);
            break;
        case 3:
                if (i == 0) {
                    printf("Buffer empty\n");
                    break;
                }
                for (k = 0; k < i; k++)
                    printf("buf[%d]: %d\n", k, buf[k].data);
                break;
        case 0:
            sem_destroy(&fill);
            sem_destroy(&empty);
            exit (0);
            break;
        }
    }
    sem_destroy(&fill);
    sem_destroy(&empty);
    return 0;
}

void *producer(void *arg)
{
    int data = *(int *) arg;

    if (sem_wait(&empty)) { /* wait */
        printf("Error: sem wait fail\n");
        pthread_exit(NULL);
    }

    buf[i].data = data;
    i++;

    if (sem_post(&fill)) { /* post */
        printf("Error: sem wait fail\n");
        pthread_exit(NULL);
    }

    pthread_exit(NULL);
}

void *consumer(void *arg)
{

    if (sem_wait(&fill)) { /* wait */
        printf("Error: sem wait fail\n");
        pthread_exit(NULL);
    }

    i--;
    *(int *) arg = buf[i].data;

    if (sem_post(&empty)) { /* post */
        printf("Error: sem wait fail\n");
        pthread_exit(NULL);
    }
    pthread_exit(NULL);
}


没有睡眠语句的输出:


Output without sleep statement:

Selection
Producer : 1 | Consumer : 2 | Display : 3 | Exit : 0 || 1

Producer
Enter data: 11

Selection
Producer : 1 | Consumer : 2 | Display : 3 | Exit : 0 || 3

Display
buf[0] = 11

Selection
Producer : 1 | Consumer : 2 | Display : 3 | Exit : 0 || 2

Consumer
Consume data: 4196464

如果在使用者块中添加了sleep语句,则将获得预期的输出(在我们的情况下为11).
由于插入了sleep语句,因此与switch的case 2语句相比,使用者线程有足够的时间来完成其执行并提供预期的输出.

If sleep statement is added in consumer block then expected output(in our case 11) is obtain.
Due to sleep statement insertion, consumer thread get enough time to complete its execution compared to case 2 statements of switch and provide expected output.

推荐答案

问题是您的主线程运行到显示消费者线程应该返回"的数据的地步.但是,主踏板和使用者之间没有同步.

The problem is that your main thread runs to the point where it displays the data that the consumer thread is supposed to "return". But there's no synchronization between the main tread and the consumer.

最简单的解决方案(仍使用线程)是让主线程加入使用者线程-这就是它可以知道使用者已经完成工作的方式.代替打电话入睡,请尝试:

the easiest solution (that still uses threads) is to have the main thread join the consumer thread - that's how it can know the consumer has completed its work. Instead of a call to sleep, try:

pthread_join(con_t, NULL);

您实际上对producer()线程有一个类似的同步问题,只是它并不明显,因为您直到获得更多输入后才对生产线程更新的数据不做任何事情.因此,竞赛条件有足够的时间来完成以产生您期望的结果的方式.

You actually have a similar synchronization problem with the producer() thread, it's just that it's not apparent because you don't do anything with the data that the produce thread updates until after getting more input. So the race condition has plenty of time to complete in a way that produces the results you expect.

但是,请记住,您的程序实际上并没有利用并发性,它会创建线程,但不会并行执行任何重要的工作.您也可以直接调用producer()consumer().

However, keep in mind that your program isn't actually taking advantage of concurrency - it creates threads, but doesn't perform any significant work in parallel. You might as well make direct calls to producer() and consumer().

这篇关于生产者-消费者在C中使用信号量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆