摘要
在Redis的Bio代码中, 需要使用for循环创建两个服务线程, 并且把两个整数0 1作为参数传到线程执行的函数中. 这个问题涉及到在linux c中, 用for循环创建多个线程并传参数时会遇到的数据竞争问题. 本文给出该问题的分析, 几段相关的错误代码的分析, 并结合redis的BIO模块代码给出总结.
第一种错误的写法
我们的目标是在一个for循环里面,调用pthread_create函数创建线程,并且把循环用到的整数i作为参数传递,希望用这个i作为线程的标志, 首先来看一段经典的错误代码:
#include <stdio.h>
#include <pthread.h>
#define THREAD_NUM 16
void *thread_func(void *arg) {
int v = *(int*)arg;
printf("v = %d\n", v);
return (void*)0;
}
int main(int argc, const char *argv[]) {
pthread_t pids[THREAD_NUM];
int i;
for (i = 0; i < THREAD_NUM; i++) {
pthread_create(&pids[i], NULL, thread_func, (void*)(&i));
}
for (i = 0; i < THREAD_NUM; i++) {
pthread_join(pids[i], NULL);
}
return 0;
}
我们这段代码能创建16个线程,然后分别传i的地址作为参数,希望能够打印出0-15这16个数字。但是通过运行我们发现,打印出来的数字有重复的,其中一次的运行结果如下:
v = 1
v = 6
v = 3
v = 4