首页 > 解决方案 > 创建多线程并根据条件递增计数器

问题描述

我正在尝试在 C 中编写一个名为 thr_incrementer 的函数,以使变量递增 N 个任务(N 由常量定义)。每个任务都分配有一个 id 标识符(介于 0 和 N-1 之间),并且它们仅在以下情况下增加一个计数器

id = 计数器 % N

现在我有这个但是,id = (counter % NTHREADS)根本不起作用。

#include<stdio.h>
#include<pthread.h>

#define NTHREADS 10

void *thr_incrementer(void *);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int counter =0;


void *thr_incrementer(void *arg){
    
    int id = 0;
    
    pthread_mutex_lock (&mutex);

    for(id = 0; id <NTHREADS ; id++){

        if (id == (counter % NTHREADS)){
            counter++;
        }
        else{
            return NULL;
        }
    }
    pthread_mutex_unlock(&mutex);

    printf("ID: %d\n",id);
    
}


int main(){
    
    pthread_t thread[NTHREADS];
    int i;

    for ( i = 0; i < NTHREADS; i++){
        pthread_create(&thread[i], NULL, thr_incrementer, NULL);
    }


    if(pthread_mutex_destroy(&mutex) != 0){
        printf("Error destorying mutex.\n");
        return -1;
    }

    printf("Thread: %ln\n",thread);
 
}

标签: linuxmultithreadingoperating-systempthreads

解决方案


现在我有这个但是,id = (counter % NTHREADS)[原文如此]根本不起作用。

当然,您代码中的测试实际上是id == (counter % NTHREADS)===)不同。该测试工作得很好,但在给出的代码中毫无意义。考虑:

  • counter最初取值 0

    int counter =0;
    
  • 每个线程都有自己的局部变量id,最初取值为 0,每个线程在运行时对其进行修改。这与问题描述的“每个任务都分配有一个 id 标识符”不匹配,代码中似乎也没有与该规定匹配的任何其他内容。

  • 每个线程基本上完成所有工作,包括对counter单个关键区域内的全局变量的所有修改。因此,不会交错其他线程的操作。

  • 每个线程id在循环中递增其变量。如果发生这种情况,id == (counter % NTHREADS)那么它也会增加counter。在这种情况下,该条件也将在下一次迭代中得到满足,因为id和 counter` 每个都加一。

  • 此外,id每个线程counter从 0 开始,整个程序从 0 开始。因此,第一个线程的增量将counter与它的增量一样多id——NTHREADS总体而言是几倍。 NTHREADS % NTHREADS是 0,所以当每个后续线程获取互斥锁时,同样的事情会再次发生。

因此,问题不在于id == (counter % NTHREADS)不起作用,而是给定您的代码,在评估时它总是正确的。

我最好的猜测是你希望每个线程counter只增加一次,轮到它自己。为此,您需要

  1. 以将分配的标识符传达给每个线程的方式实现“为每个任务分配一个 id 标识符”的规范。为不同的线程提供不同的数据通常涉及使用 的第四个参数pthread_create(),线程函数将其作为其(唯一)参数接收。

  2. 将条件变量与互斥锁一起使用,以使线程在等待轮到它们时暂停操作。您可以在 SO 上找到许多关于如何正确执行此操作的答案。

  3. 当一个线程轮到计数器递增时,它只执行一次递增,而不是多次递增,并且它不会修改自己分配的 ID。

还有很多细节需要你去解决。我把这些作为他们打算做的练习。


推荐阅读