gpt4 book ai didi

c - 使用互斥量的意外结果

转载 作者:太空狗 更新时间:2023-10-29 12:04:27 25 4
gpt4 key购买 nike

我必须使用 N 个线程确定给定值在整数数组中的哪个位置,并将这些值显示在屏幕上。我认为我可以通过使用一个存储索引的数组来解决这个问题,并借助一个跟踪找到的位置数量的变量。共享变量,我正在使用互斥锁。问题是我在输出上有重复的位置。我做错了什么?

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

#define P 10
#define SIZE (sizeof(elementsList)/sizeof(elementsList[0]))



static int elementsList[] = { 1,2,3,4,5,6,7,8,3,10,11,12,3,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,3,11,12,13,14,3,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,3 };

static int positions[SIZE];
pthread_mutex_t mutex;
volatile int count = 0;
static int value_to_be_found;
static pthread_t threads[P];

void *getPositions(void *arg){
int *argPtr = arg;
int start = *argPtr;
int i;


for(i = start; i < SIZE; i+= P){
if(elementsList[i] == value_to_be_found){
pthread_mutex_lock(&mutex);
count++;
positions[count] = i;
pthread_mutex_unlock(&mutex);
}
}

}

int main(){

int th;
int ret;
int i;
printf("Enter the value to be found: \n");
scanf("%d",&value_to_be_found);

for(th = 0; th < P; th++){
ret = pthread_create(&threads[th],NULL,&getPositions,&th);
if(ret){
printf("Error!\n");
exit(-1);
}
}

for(th = 0; th < P; th++){
pthread_join(threads[th],NULL);
}
printf("The positions where % was found are: \n",value_to_be_found);
for(i = 1; i <= count; i++){
printf("%d. position #%d\n",i,positions[i]);
}
return 0;

}

编辑:输入值为 3输出并非始终相同,但这是输出之一:

position #2
position #12
position #84
position #36
position #36
position #43
position #53
position #8
position #48
position #19

应该显示的是:

position #70
position #2
position #12
position #43
position #53
position #84
position #36
position #8
position #48
position #19

最佳答案

这一行引入了竞争条件:

ret = pthread_create(&threads[th], NULL, &getPositions, &th);

当您传递 th 的地址时到每个线程。

然后在下一次迭代中,地址指向的值发生变化。这甚至可能发生在上一次迭代中创建的线程获取地址、取消引用它并通过以下行将值存储在本地之前:

int start = *argPtr;

因此不能保证每个线程都为start存储了不同的值.


对此的肮脏解决方案是滥用传递给线程函数的指针作为整数,例如:

ret = pthread_create(&threads[th], NULL, &getPositions, (void *)th);

在线程函数里面做

int start = (int) argPtr;

只要 int 就有效比 void * 短.为了安全起见,请参阅此问题,请使用 intptr_t作为 th 的类型和 start , 作为 intptr_t保证与 void * 大小相同.


干净的解决方案是定义一个数组来保存起始值并将第 ith 元素的地址传递给线程功能:

int starts[P] = {0};

...

int(main(void)
{
...

for(th = 0; th < P; th++)
{
starts[th] = th;
ret = pthread_create(&threads[th], NULL, &getPositions, &start[th]);

还有 getPositions()函数遗漏了一个 return声明,但这不会导致问题,如 pthread_join()不使用任何线程返回的值。


另外^2:代码遗漏了 exit() 的原型(prototype).包括<stdlib.h>让它就位。

关于c - 使用互斥量的意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20195751/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com