【问题标题】:How to kill waiting threads in producer consumer problem如何杀死生产者消费者问题中的等待线程
【发布时间】:2020-09-22 15:27:58
【问题描述】:

code snippet source-Remzi

我正在使用锁和条件变量编写生产者消费者问题。这是一个简单的程序,我在缓冲区中使用 int。生产者完成生产后如何阻止消费者等待?

void do_fill(int i){
    buffer[fill_ptr].chunkNumber = i;
    buffer[fill_ptr].size = 1024;
    buffer[fill_ptr].startPointer = dst + (i * 1024);
    fill_ptr = (fill_ptr+1) % max;
    numfull++;
}

int do_get(){
    int temp_chunk = buffer[use_ptr].chunkNumber;
    char *temp_start = buffer[use_ptr].startPointer;
    int temp_size = buffer[use_ptr].size;
    use_ptr = (use_ptr+1) %max;
    printf("%d  %c  %d \n", temp_chunk,*temp_start,temp_size);
    numfull--;
    return temp_chunk;
}

void *producer(void *arg) 
{
    
    for (int cant = 0; cant < 5; ++cant)
    {
        printf("IN PRODUCER\n");
        pthread_mutex_lock(&m);           // p1
        while (numfull == max)  // p2
            pthread_cond_wait(&empty, &m);  // p3
        do_fill(cant);               // p4
        pthread_cond_signal(&fill);       // p5
        pthread_mutex_unlock(&m);  
    } 
}

void *consumer(void *arg) 
{  
    for (int i=0;i<5;i++)
    {
        printf("IN CONS\n");
        pthread_mutex_lock(&m);
               // c1
        while (numfull == 0)
        {
          // c2
            pthread_cond_wait(&fill, &m);
        }  // c3
        int temp = do_get();
        pthread_cond_signal(&empty);      // c5
        pthread_mutex_unlock(&m);        // c6
    }
}

【问题讨论】:

  • edit您的问题并将您的代码复制并粘贴为文本而不是显示屏幕截图。见meta.stackoverflow.com/questions/285551/… 没有看到缺失的功能就很难给出建议。也许有一种方法可以检测“没有更多数据”/EOF 条件。

标签: c multithreading


【解决方案1】:

您可以引入第二个变量bool is_finished = false,它与变量numfull 一样,受互斥锁m 保护。当生产者完成后,它会将这个变量设置为true,并向条件变量fill发出信号。

这就是函数producer 的样子:

void *producer(void *arg) 
{ 
    for (int cant = 0; cant < 5; ++cant)
    {
        printf("IN PRODUCER\n");
        pthread_mutex_lock(&m);
        while (numfull == max)
            pthread_cond_wait(&empty, &m);
        do_fill(cant);
        pthread_mutex_unlock(&m);
        pthread_cond_signal(&fill);
    }
    pthread_mutex_lock(&m);
    is_finished = true;
    pthread_mutex_unlock(&m);
    pthread_cond_signal(&fill); 
}

consumer 函数当然必须进行相应的更改,例如:

void *consumer(void *arg) 
{  
    for (;;) //infinite loop
    {
        printf("IN CONS\n");
        pthread_mutex_lock(&m);
        while ( numfull == 0 && !is_finished )
        {
            pthread_cond_wait(&fill, &m);
        }
        if ( numfull == 0 )
        {
            //is_finished must be true
            pthread_mutex_unlock(&m);
            break;
        }
        int temp = do_get();
        pthread_mutex_unlock(&m);
        // It is generally recommended to signal only after
        // releasing the mutex, otherwise the awakened thread
        // may block on the mutex.
        pthread_cond_signal(&empty);
    }
}

在函数consumer 中,我还将for 循环更改为无限循环,因为将其限制为5 次迭代没有意义。它应该等待生产者发出完成的信号。

【讨论】:

  • 消费者线程不会等待,但在这种情况下,for循环仍将继续,它将继续打印垃圾值
  • @AdityaKulkarni:你当然必须在退出while循环后检查两个谓词(numfullis_finished),以确定是继续消费还是停止。
  • @AdityaKulkarni:我现在添加了完整的consumer 函数。
  • 在你的问题中,我不明白为什么consumerproducer 中的for 循环都限制为5 次迭代。将consumer 循环设为无限会更有意义,这样它只会在生产者发出完成信号时退出循环。只有 producer 应该限制为 5 次迭代。
  • 一般情况下,条件变量的谓词应该受到互斥体的保护。但是,您正在修改 is_finished 而不首先获取互斥锁。我不确定这是否是个好主意。但是,在这种情况下,它可能无关紧要,因为它是唯一写入该变量的线程,而所有其他读取都只从它读取。至少如果所有写入和读取操作都是原子的,那应该不是问题。但为了安全起见,我仍然建议锁定互斥锁。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-16
  • 1970-01-01
  • 2013-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多