我遇到了将参数传递给新线程的问题,我有以下内容
doRowOffset[0] = 0;
for(threads = 1; threads < NUMTHREADS; threads++){
doRowOffset[threads] = threads;
printf("Do row: %d\n", doRowOffset[threads]);
pthread_create(&threadHandler[threads], NULL, multiplyRows, (void *) &doRowOffset[threads]);
}
和
void * multiplyRows(void * dealWithRows){
int offset = *((int *) dealWithRows);
printf("%d\n", *((int *) dealWithRows));
printf("Offset: %d\n", offset);
printf("Size: %d\n", partitionSize/NUMTHREADS);
printf("Calculated Offset: %d\n", offset*partitionSize/NUMTHREADS);
...
现在我希望看到以下输出
行:1
1
偏移量:1
尺寸:2
计算的偏差:2
然而,当我进入线程时,我继续获取垃圾值或者为dealWithRows获取0,我在参数传递方面做错了吗?
答案 0 :(得分:2)
如果doRowOffset
是int
,您不应该看到垃圾,除非创建功能的线程完成并且您已分配变量堆栈,它被覆盖。
但请注意,只有一个变量,并且您正在传递其地址,因此当线程启动时,它可以看到更新的值。
传递实际值:
pthread_create(&threadHandler[threads], NULL, multiplyRows, (void *) threads);
void * multiplyRows(void * dealWithRows){
int offset = (int) dealWithRows);
}
答案 1 :(得分:2)
如果你传递了一个正在变化的变量的地址,你必须期望它可能会改变你: - )
可能发生的是你将doRowOffset
设置为1(例如)然后启动线程。在该线程启动并取消引用其指针之前,您将为下一个线程更改doRowOffset
。
然后,当第一个线程最终取消引用该地址时,您已经更改了基础值。
有两种方法可以解决这个问题。第一种是同步主线程和子线程,以便主线程等待,直到子项取消引用变量并在本地存储该值。只有这样,主线程才会改变它即将启动的下一个线程的变量。但是,这种做法违背了线程的目的: - )
另一种方法是将实际的整数值(不是地址)转换为void指针,该指针将传递给线程函数。这意味着该值将被复制到线程函数的堆栈而不是地址,然后主线程将无法影响它。
类似的东西:
pthread_create (&threadHandler[threads], NULL, multiplyRows,
(void *) doRowOffset); // <<-- Note, removed the '&'.
在主线程中:
int offset = (int) dealWithRows;
在子线程中。