linux - 创建多线程并根据条件递增计数器
问题描述
我正在尝试在 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);
}
解决方案
现在我有这个但是,
id = (counter % NTHREADS)
[原文如此]根本不起作用。
当然,您代码中的测试实际上是id == (counter % NTHREADS)
(==
与=
)不同。该测试工作得很好,但在给出的代码中毫无意义。考虑:
counter
最初取值 0int 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
只增加一次,轮到它自己。为此,您需要
以将分配的标识符传达给每个线程的方式实现“为每个任务分配一个 id 标识符”的规范。为不同的线程提供不同的数据通常涉及使用 的第四个参数
pthread_create()
,线程函数将其作为其(唯一)参数接收。将条件变量与互斥锁一起使用,以使线程在等待轮到它们时暂停操作。您可以在 SO 上找到许多关于如何正确执行此操作的答案。
当一个线程轮到计数器递增时,它只执行一次递增,而不是多次递增,并且它不会修改自己分配的 ID。
还有很多细节需要你去解决。我把这些作为他们打算做的练习。
推荐阅读
- azure-ad-b2c - 如何:当用户取消注册时重新启动 Azure AD B2C UserJourney
- javascript - 从 API 获取 - 特定 API 错误与一般 HTTP 错误
- terraform - 如何将服务器ID元组展平为字符串?
- asp.net - 单击asp.net mvc中的ng-click后如何避免页面重新加载
- visual-studio - 查看解决方案操作:重新定位项目 - 如何抑制它?
- d3.js - 禁用缩放但在 foreignObject 上检索滚动
- javascript - 如何使一个元素出现而不触发同一类的其他元素
- rust - 如何存储线程的 JoinHandle 以便稍后关闭它
- logging - 如何在kibana中显示hybris自定义扩展日志?
- c# - c# 如何从列表中的记录中只获取一个值?