【问题标题】:Readers-Writers problem with pthreads resulting in only 1 readerpthreads的Readers-Writers问题导致只有1个读者
【发布时间】:2019-09-09 13:27:35
【问题描述】:

我的任务是为 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);
    }
}

【问题讨论】:

  • 对于pthread_cond_wait(&qEmpty, &mutex);,谁在发出 qEmpty 条件的信号?
  • @user7176709 我明白了,添加了。不确定是否在正确的地方。但问题仍然存在:(
  • 我不知道你为什么要写这个:while(isEmpty(q)) { pthread_cond_signal(&qEmpty); pthread_cond_wait(&qElement, &mutex); } ' In the writer`线程。为什么要检查写入线程中的空条件?
  • @user7176709 我的错误我在stackoverflow中编辑了错误的代码部分。问题仍然存在。也许我在某处造成了竞争状况?
  • 你用的是什么调度器?

标签: c pthreads producer-consumer


【解决方案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' 的地址作为参数传递

【讨论】:

    【解决方案2】:

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

    所说的“随机方式”是指所有线程可以在程序过程中被调度一次,或者在整个过程中只调度一个线程。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-08
      • 2011-08-29
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      • 2022-08-20
      • 1970-01-01
      相关资源
      最近更新 更多