我使用2个未同步的线程将全局volatile int从0增加到10000000。正如所料,int有时会以10000001结束。
但是,我也要计算两个线程使用特定于线程的局部变量执行增量操作的次数,并且这一次过大。代码如下:
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
volatile int x = 0;
void* incThread(void* x) {
int* y;
y = malloc(sizeof(int));
*y = 0;
printf("tstart\n");
while(*((int*)x) < 10000000) {
*y = *y + 1;
*((int*)x) = *((int*)x) + 1;
if(*y % 1000000 == 0) {
printf(">thread at %i\n", *y));
}
}
printf("tend\n");
pthread_exit(y);
}
int main(int argc, char* argv[]) {
pthread_t thread1;
pthread_t thread2;
volatile int* xp;
xp = &x;
int* ret1;
int* ret2;
printf("\n\n\nTHREAD LAUNCH PROGRAM\n");
printf("-------------------------------------\n");
printf("I'll launch two threads.\n");
printf("Both will try incrementing the global value x to 10000000 before exiting.\n\n");
pthread_create(&thread1, NULL, incThread, (void*)xp);
pthread_create(&thread2, NULL, incThread, (void*)xp);
pthread_join(thread1, (void**) &ret1);
pthread_join(thread2, (void**) &ret2);
printf(" Thread01 exited after %i loops.\n", *ret1);
printf(" Thread02 exited after %i loops.\n", *ret2);
printf(" --------\n");
printf(" => %i total\n", ((*ret1)+(*ret2)));
printf("\n");
printf("x ended up at %i.\n", x);
printf("\n");
return 0;
}
因此,运行此命令将为线程的迭代计数器(incThread()中的int y)打印出错误的结果;例如,Thread01的y=5801001和Thread02的y=5456675,总计超过预期值10000000的112%。同时,x本身也达到了10000000或更高的值,正如预期的那样。
给出了什么?迭代计数怎么会这么高?
操作系统信息和我认为应该发生的事情:
这整件事正在运行的虚拟Debian7.1将其关联设置为一个CPU核心。
我希望虚拟操作系统在程序进程中打开3个线程。然后,作为常规执行周期的一部分,当它从一个进程迭代切换到另一个进程时,它还应该在每个进程线程(在本例中是主线程和自定义线程1&2)之间保持切换,只要它专注于该特定进程。
所以,有一个主线程启动t1和t2,然后等待线程1完成,一旦完成,它就等待线程2完成,然后继续打印结果。但据我所知,这些都不能解释y怎么能偏离x这么大。
最佳答案
之所以会发生这种情况,是因为x可能在两个线程的每次迭代中递增一次。
例如,
t1:读取x值(x为5)
t2:读取x值(x为5)
t1:增量存储x(x为6)
t2:增量存储x(x为6)
所以两个线程都完成了一次迭代,但是x的值只增加了一次。理论上,每个线程都有可能运行多达10000000次。