pthread_join 似乎修改了我的循环索引
pthread_join seems to modify my loop index
我的代码(见下文)产生了奇怪的行为。输出为:
Testing whether there are problems with concurrency ...rc is 0. i is 0
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 3. i is 2
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 3. i is 2
.rc is 3. i is 3
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 3. i is 2
.rc is 3. i is 3
.rc is 3. i is 4
.rc is 0. i is 0
Segmentation fault (core dumped)
我试图调试它,但只发现我在 pthread_join 之后立即重置为 0。这使我得出结论,修改必须发生在某个地方。但我找不到任何东西。我觉得有点傻,因为这并不是一段很难的代码。我没有注意到什么?
操作系统是 Ubuntu 14.04。 N_THREADS当前设置为10,N_RUNS为10000。
主线程:
pthread_t threads[N_THREADS];
pthread_attr_t attr;
int i;
int rc;
int status;
printf("Testing whether there are problems with concurrency ...");
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for (i = 0; i < N_THREADS; i++){
if (i) {
rc = pthread_create(&(threads[i]), &attr, addRemove, 0);
} else {
rc = pthread_create(&(threads[i]), &attr, readStuff, 0);
}
if (rc) return rc;
}
for(i = 0; i < N_THREADS; i++) {
rc = pthread_join(threads[i], (void*) &status);
// if(rc == 3)
printf("rc is %d. i is %d\n", rc, i);
// if (rc) return rc;
if (status) return status;
printf(".");
}
pthread_attr_destroy(&attr);
return 0;
工作线程:
void* readStuff(void* a)
{
int i;
for (i = 0; i< N_RUNS; i++){
;
}
pthread_exit((void*)0);
}
void* addRemove(void* a)
{
int i;
for (i = 0; i< N_RUNS; i++){
;
}
pthread_exit((void*)0);
}
除了主线程和上面代码中创建的线程外,没有其他线程。
我认为您的问题出在 pthread_join
上。来自手册页:
int pthread_join(pthread_t thread, void **retval);
...
If retval is not NULL, then pthread_join() copies the exit status of the tar‐
get thread (i.e., the value that the target thread supplied to
pthread_exit(3)) into the location pointed to by *retval. If the target
thread was canceled, then PTHREAD_CANCELED is placed in *retval.
请注意,它需要一个 void **
,这意味着它会用 void *
(64 位上的大小 8)覆盖 retval
指向的内容。您正在传递一个 int *
(即 &status
),它是一个指向大多数平台上大小为 4 的对象的指针。
因此,pthread_join
将覆盖内存。相反,根据函数原型将 status
声明为 void *
。
您也在测试status
;我不知道你想在这里实现什么。
一般来说,使用 -Wall
编译会显示这些错误。
我的代码(见下文)产生了奇怪的行为。输出为:
Testing whether there are problems with concurrency ...rc is 0. i is 0
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 3. i is 2
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 3. i is 2
.rc is 3. i is 3
.rc is 0. i is 0
.rc is 3. i is 1
.rc is 3. i is 2
.rc is 3. i is 3
.rc is 3. i is 4
.rc is 0. i is 0
Segmentation fault (core dumped)
我试图调试它,但只发现我在 pthread_join 之后立即重置为 0。这使我得出结论,修改必须发生在某个地方。但我找不到任何东西。我觉得有点傻,因为这并不是一段很难的代码。我没有注意到什么?
操作系统是 Ubuntu 14.04。 N_THREADS当前设置为10,N_RUNS为10000。
主线程:
pthread_t threads[N_THREADS];
pthread_attr_t attr;
int i;
int rc;
int status;
printf("Testing whether there are problems with concurrency ...");
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for (i = 0; i < N_THREADS; i++){
if (i) {
rc = pthread_create(&(threads[i]), &attr, addRemove, 0);
} else {
rc = pthread_create(&(threads[i]), &attr, readStuff, 0);
}
if (rc) return rc;
}
for(i = 0; i < N_THREADS; i++) {
rc = pthread_join(threads[i], (void*) &status);
// if(rc == 3)
printf("rc is %d. i is %d\n", rc, i);
// if (rc) return rc;
if (status) return status;
printf(".");
}
pthread_attr_destroy(&attr);
return 0;
工作线程:
void* readStuff(void* a)
{
int i;
for (i = 0; i< N_RUNS; i++){
;
}
pthread_exit((void*)0);
}
void* addRemove(void* a)
{
int i;
for (i = 0; i< N_RUNS; i++){
;
}
pthread_exit((void*)0);
}
除了主线程和上面代码中创建的线程外,没有其他线程。
我认为您的问题出在 pthread_join
上。来自手册页:
int pthread_join(pthread_t thread, void **retval); ... If retval is not NULL, then pthread_join() copies the exit status of the tar‐ get thread (i.e., the value that the target thread supplied to pthread_exit(3)) into the location pointed to by *retval. If the target thread was canceled, then PTHREAD_CANCELED is placed in *retval.
请注意,它需要一个 void **
,这意味着它会用 void *
(64 位上的大小 8)覆盖 retval
指向的内容。您正在传递一个 int *
(即 &status
),它是一个指向大多数平台上大小为 4 的对象的指针。
因此,pthread_join
将覆盖内存。相反,根据函数原型将 status
声明为 void *
。
您也在测试status
;我不知道你想在这里实现什么。
一般来说,使用 -Wall
编译会显示这些错误。