pthreads的Readers-Writers问题导致仅1个阅读器

时间:2019-04-19 08:46:26

标签: c pthreads producer-consumer

我要做的任务是为posix pthreads创建读写器问题的解决方案。我产生了3位读者和1位作家。

任务规范要求一次将值添加到队列2中(写程序)。读取器一次使一个队列出队列(当队列中存在一个值时)。队列已经过测试并且可以正常工作。

我遇到的问题是在运行程序时,它导致只有1个读取器线程实际上大部分时间都在读取 。有时重复执行将导致全部3个阅读器被使用。但大多数情况下,仅使用1个阅读器。我不确定为什么会发生这种奇怪的行为。

先谢谢了。

Expected (Sometimes): 
TID: -684419328
TID: -684419328
TID: -673929472
TID: -673929472
TID: -694909184
TID: -694909184
...
Actual (Sometimes): 
TID: -684419328
TID: -684419328
TID: -684419328
TID: -684419328
TID: -684419328
TID: -684419328
...
pthread_cond_t qServiced = PTHREAD_COND_INITIALIZER;
pthread_cond_t qElement = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
#include "rw.h"
#include "queue.h"

queue* q; 

void* reader()
{
    int serviced = 0; 
    int x; 

    while(!fin)
    {
        pthread_mutex_lock(&mutex);
        counter++; 

        while(isEmpty(q))
        {
            pthread_cond_signal(&qEmpty);
            pthread_cond_wait(&qElement, &mutex); e 
        }

        printf("TID: %d\n", (int)pthread_self());

        num* n = dequeue(q); //Take one task 

        printf("Num1: %d\n", n->num1);
        printf("Num2: %d\n", n->num2);

        serviced++;
        pthread_cond_signal(&qServiced); //Signal that task has been serviced
        pthread_mutex_unlock(&mutex);
    }
}

2 个答案:

答案 0 :(得分:1)

以下建议的代码仅适用于'read()'线程,但应为您提供有关如何编写线程的想法。

void* reader( void *arg )
{
    int *fin = (int*)arg;

    int serviced = 0; 

    while( !(*fin) )
    {
        printf("TID: %d\n", (int)pthread_self());

        pthread_mutex_lock(&mutex);
        counter++; 
        num* n = dequeue(q); //Take one task 
        pthread_mutex_unlock(&mutex);

        if( n )
        {
            printf("Num1: %d\n", n->num1);
            printf("Num2: %d\n", n->num2);
            serviced++;
        }

        else
        {
            printf( "no queue entries available\n" );
            sleep(1);
        }
    }
    pthread_exit( NULL );
}

请注意,互斥锁仅在线程执行可能导致“竞赛”状态的操作时锁定。

建议的代码假设(因为从未发布队列处理代码)如果队列为空,dequeue()返回NULL

注意:当没有可用的队列条目时,线程会休眠一段时间

这假设main()函数在调用pthread_create()

时将'fin'的地址作为参数传递

答案 1 :(得分:0)

线程是由调度程序以一种调度机制调度的。但是作为程序员,您应该假设它可以是任何随机方式和代码。

通过说“随机方式”,我的意思是所有线程都可以在程序过程中被调度一次,或者在整个过程中仅一个线程被调度。

线程可能会以随机方式安排。我希望这能回答您的问题。

如果您想要执行执行的特定方式(例如:所有线程在第二次读取线程之前读取一次),则必须进行相应的编码。您可以使用互斥量,信号量,条件信号,标志以及所有这些的组合来实现此目的。