繁体   English   中英

多线程,消费者和生产者

[英]Multi-threading, consumers and producers

由于我是本主题的新手,因此我在多线程方面遇到问题。 下面的代码是我从大学获得的代码。 它只有几个版本,而我大部分都了解。 但是我不太了解nready.nready变量以及所有这些线程条件。 谁能描述这两个在这里的工作方式? 为什么我不能仅通过互斥量同步线程的工作?

#include    "unpipc.h"

#define MAXNITEMS       1000000
#define MAXNTHREADS         100

    /* globals shared by threads */
int     nitems;             /* read-only by producer and consumer */
int     buff[MAXNITEMS];

struct {
pthread_mutex_t mutex;
pthread_cond_t  cond;
int             nput;
int             nval;
int             nready;
} nready = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER };

void    *produce(void *), *consume(void *);

/* include main */
int
main(int argc, char **argv)
{
int         i, nthreads, count[MAXNTHREADS];
pthread_t   tid_produce[MAXNTHREADS], tid_consume;

if (argc != 3)
    err_quit("usage: prodcons5 <#items> <#threads>");
nitems = min(atoi(argv[1]), MAXNITEMS);
nthreads = min(atoi(argv[2]), MAXNTHREADS);

Set_concurrency(nthreads + 1);
    /* 4create all producers and one consumer */
for (i = 0; i < nthreads; i++) {
    count[i] = 0;
    Pthread_create(&tid_produce[i], NULL, produce, &count[i]);
}
Pthread_create(&tid_consume, NULL, consume, NULL);

    /* wait for all producers and the consumer */
for (i = 0; i < nthreads; i++) {
    Pthread_join(tid_produce[i], NULL);
    printf("count[%d] = %d\n", i, count[i]);    
}
Pthread_join(tid_consume, NULL);

exit(0);
}
/* end main */

void *
produce(void *arg)
{
    for ( ; ; ) {
    Pthread_mutex_lock(&nready.mutex);
    if (nready.nput >= nitems) {
        Pthread_mutex_unlock(&nready.mutex);
        return(NULL);       /* array is full, we're done */
    }
    buff[nready.nput] = nready.nval;
    nready.nput++;
    nready.nval++;
    nready.nready++;
    Pthread_cond_signal(&nready.cond);
    Pthread_mutex_unlock(&nready.mutex);
    *((int *) arg) += 1;
}
}

/* include consume */
void *
consume(void *arg)
{
int     i;

for (i = 0; i < nitems; i++) {
    Pthread_mutex_lock(&nready.mutex);
    while (nready.nready == 0)
        Pthread_cond_wait(&nready.cond, &nready.mutex);
    nready.nready--;
    Pthread_mutex_unlock(&nready.mutex);

    if (buff[i] != i)
        printf("buff[%d] = %d\n", i, buff[i]);
}
return(NULL);
}
/* end consume */
pthread_mutex_lock(&nready.mutex);
while (nready.nready == 0)
    pthread_cond_wait(&nready.cond, &nready.mutex);
nready.nready--;
pthread_mutex_unlock(&nready.mutex);

该结构的全部目的是确保在执行相应的动作(nready.nready--)时条件(nready.nready == 0)仍然为true,或者-如果不满足条件-等待直到它满足无需占用CPU时间。

您只能使用互斥锁,以检查条件是否正确并自动执行相应的操作。 但是,如果条件不满足,您将不知道该怎么办。 等待? 到什么时候? 再检查一次? 释放互斥并在之后立即重新检查? 那会浪费CPU时间...

pthread_cond_signal()和pthread_cond_wait()可以解决此问题。 您应该检查他们的手册页。

简而言之,pthread_cond_wait的作用是使调用线程进入休眠状态,并以原子方式释放互斥锁,直到发出信号为止。 因此,这是一个阻止功能。 然后可以通过调用信号或从其他线程广播来重新安排线程。 当线程发出信号时,它将再次获取互斥量并退出wait()函数。

到目前为止,您知道

  1. 你的情况是真实的,
  2. 您持有互斥量。

因此,您可以做任何需要处理的数据。

但是要小心,如果您不确定另一个线程是否会发出信号,则不应调用wait。 这是死锁的一个非常常见的来源。

当线程接收到信号时,它将被放入准备进行调度的线程列表中。 在实际执行线程时,您的条件(即nread.nready == 0)可能再次为假。 因此是while(以重新检查线程是否被唤醒)。

"But I don't really understand the nready.nready variable"

this results from the struct instance being named 'nready' and there 
is a field within the struct named 'nready'

IMO: a very poor design to have two different objects being given the same name

the nready field of the nready struct seems to be keeping track of the number of 
items that have been 'produced'

1) nready日提交的struct nready用于粘性多少任务准备消耗,即在阵列的其余任务buff nready.nready++; 仅当生产者将一个新项目放入数组buffnready.nready--;时才执行该nready.nready--; 仅当消耗使物品失去buff时执行。 使用is变量,程序员可以始终跟踪要处理的任务数量。

2)

pthread_mutex_lock(&nready.mutex);
while (nready.nready == 0)
    pthread_cond_wait(&nready.cond, &nready.mutex);
nready.nready--;
pthread_mutex_unlock(&nready.mutex);

上面的语句是常见条件变量的用法。 您可以检查POSIX线程编程条件变量,以获取有关条件变量的更多信息。

为什么不能只使用互斥锁? 您可以一次又一次轮询互斥锁。 显然,这很浪费CPU时间,并且可能会严重影响系统性能。 相反,您希望消耗者在buff没有更多物品时在睡眠中等待,并在生产者将新物品放入buff时唤醒。 条件变量在此充当此角色。 当没有任何项时(nready.nready == 0), pthread_cond_wait()函数将当前线程置于睡眠状态,从而节省了宝贵的CPU时间。 当有新商品到达时, Pthread_cond_signal()唤醒消费者。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM