我必须确定使用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
答案 0 :(得分:3)
这一行引入了种族关系:
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 *
保证与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]);
的大小相同。
清洁解决方案 将定义一个数组来保存起始值并将i th 元素的地址传递给线程功能:
getPositions()
同样,return
函数错过了pthread_join()
语句,但这不会导致问题,因为exit()
不使用任何线程返回的值。
另外^ 2:代码错过了<stdlib.h>
的原型。包括{{1}}以使其到位。