多线程程序如何在 C 中工作? [英] How Multi-threaded program works in C?

查看:65
本文介绍了多线程程序如何在 C 中工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一个完全的新手,我一直在编写固定缓冲区大小的生产者-消费者问题,我观察到的缓冲区大小 1 与我预期的非常不同.我打印x-->"当我产生 x 和--> x"时当 x 被消耗时.我得到的输出是这样的:\

I am a complete newbie and I have been coding producer-consumer problem with fixed buffer size what I observed for buffer-size 1 is very different from what I expected. I print "x-->" when I produce x and "-->x" when x is consumed. The output I get is like this: \

0 --->
1 --->
2 --->
---> 0
---> 1
---> 2
3 --->
4 --->
5 --->
---> 3
---> 4
---> 5

我很困惑 1,2,3 是如何一次复制然后一次消耗 1,2,3 的,有人可以解释一下吗.

I am confused about how 1,2,3 reproduced at once and then 1,2,3 consumed at once can someone explain, please.

这是我的代码

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define BUFFER_SIZE 1
#define OVER (-1)


int filled = 0;

struct prodcons {
    int buffer[BUFFER_SIZE];      /* the actual data */
    pthread_mutex_t lock;         /* mutex ensuring exclusive access to buffer */
    int readpos, writepos;        /* positions for reading and writing */
    pthread_cond_t notempty;      /* signaled when buffer is not empty */
    pthread_cond_t notfull;       /* signaled when buffer is not full */
};

void init(struct prodcons * b)
{
    pthread_mutex_init(&b->lock, NULL);
    pthread_cond_init(&b->notempty, NULL);
    pthread_cond_init(&b->notfull, NULL);
    b->readpos = 0;
    b->writepos = 0;
}

void put(struct prodcons * b, int data)
{
    pthread_mutex_lock(&b->lock);
    if(BUFFER_SIZE == 1) {
        if(filled) {
            pthread_cond_wait(&b->notfull, &b->lock);
        }
        b->buffer[0] = data;
        filled = 1;
    }
    else {
        /* Wait until buffer is not full */
        while ((b->writepos + 1) % BUFFER_SIZE == b->readpos) {
            pthread_cond_wait(&b->notfull, &b->lock);
            /* pthread_cond_wait reacquired b->lock before returning */
        }
        /* Write the data and advance write pointer */
        b->buffer[b->writepos] = data;
        b->writepos++;
        if (b->writepos >= BUFFER_SIZE) b->writepos = 0;
        /* Signal that the buffer is now not empty */
    }

    pthread_cond_signal(&b->notempty);
    pthread_mutex_unlock(&b->lock);
}

int get(struct prodcons * b)
{
    int data = 0;
    pthread_mutex_lock(&b->lock);
    if(BUFFER_SIZE == 1) {
        if(!filled) {
            pthread_cond_wait(&b->notempty, &b->lock);
        }
        data = b->buffer[0];
        filled = 0;
    }
    else {
        /* Wait until buffer is not empty */
        while (b->writepos == b->readpos) {
            pthread_cond_wait(&b->notempty, &b->lock);
        }
        /* Read the data and advance read pointer */
        data = b->buffer[b->readpos];
        b->readpos++;
        if (b->readpos >= BUFFER_SIZE) b->readpos = 0;
        /* Signal that the buffer is now not full */
    }
    pthread_cond_signal(&b->notfull);
    pthread_mutex_unlock(&b->lock);
    return data;
}

struct prodcons buffer;

void * producer(void * data)
{
    int n;
    for (n = 0; n < 10000; n++) {
        printf("%d --->\n", n);
        put(&buffer, n);
    }
    put(&buffer, OVER);
    return NULL;
}

void * consumer(void * data)
{
    int d;
    while (1) {
        d = get(&buffer);
        if (d == OVER) break;
        printf("---> %d\n", d);
    }
    return NULL;
}
int main(void)
{
    pthread_t th_a, th_b;
    void * retval;
    init(&buffer);
    /* Create the threads */
    pthread_create(&th_a, NULL, producer, 0);
    pthread_create(&th_b, NULL, consumer, 0);
    /* Wait until producer and consumer finish. */
    pthread_join(th_a, &retval);
    pthread_join(th_b, &retval);
    return 0;
}

推荐答案

不能保证输出如您所愿.我实现了一个时间戳,它显示了 putget 方法被调用的时间(时间是相对于 init 被调用的时间):

The output is not guaranteed as you expect it. I implemented a timestamp, which shows, when the put and get methods are called (time is relative to when init was called):

[ 44491 ns] 0 --->
[115427 ns] 1 --->
[153189 ns] ---> 0
[178376 ns] 2 --->
[182891 ns] 3 --->
[183518 ns] ---> 1
[188542 ns] ---> 2
[198661 ns] 4 --->
[203461 ns] ---> 3
[206636 ns] ---> 4
[204180 ns] 5 --->
[212146 ns] 6 --->
[221019 ns] ---> 5
[224146 ns] ---> 6
[221877 ns] 7 --->
[230976 ns] 8 --->
[232130 ns] 9 --->
[232347 ns] ---> 7
[237920 ns] ---> 8
[239051 ns] ---> 9
[239312 ns] 10 --->
[244770 ns] 11 --->
[245918 ns] 12 --->
[246106 ns] ---> 10
...

你应该知道,stdout 是两个线程共享的,那么锁是怎么实现的,谁知道呢.

You should know, that stdout is shared by the two threads, so how the locking is implemented there, who knows.

如果你想要同步输出,你必须把 printf 放入同步部分(在 putget 方法中访问你的缓冲区之后).

If you want synchronized output, you have to put printf into the synchronized sections (after accessing your buffer in the put and get methods).

然后你得到输出:

[ 31900 ns] 0 --->
[ 77228 ns] ---> 0
[ 85722 ns] 1 --->
[ 90959 ns] ---> 1
[ 95490 ns] 2 --->
[ 99591 ns] ---> 2
[103447 ns] 3 --->
[107385 ns] ---> 3
[111325 ns] 4 --->
[115215 ns] ---> 4
[119143 ns] 5 --->
[123066 ns] ---> 5
[126962 ns] 6 --->
[130860 ns] ---> 6
[134561 ns] 7 --->
[138427 ns] ---> 7
[142188 ns] 8 --->
[146115 ns] ---> 8
[149797 ns] 9 --->
[153534 ns] ---> 9
[157856 ns] 10 --->
[161631 ns] ---> 10
...

这篇关于多线程程序如何在 C 中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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