Chinaunix
标题:
多线程环境中的static变量问题【已解决】
[打印本页]
作者:
edshea
时间:
2011-09-20 12:51
标题:
多线程环境中的static变量问题【已解决】
本帖最后由 crazyhadoop 于 2011-09-20 18:13 编辑
以前被问过一个多线程环境中的static变量问题,到现在一直没搞明白,
今天写了一小段代码,但解释不清,大家帮忙看看吧
multiThread_staticVar.c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
#define INIT 1
#define MAX 10
//static int v = INIT;
void *f (void *arg)
{
static int v = INIT;
printf("Thread ID = %ld, arg = %d, v = %d\n", syscall(SYS_gettid), *(int *)arg, v);
while (v < MAX) {
v += *(int *)arg;
// printf("v = %d\n", v);
printf("Thread ID = %ld, arg = %d, v = %d\n", syscall(SYS_gettid), *(int *)arg, v);
sleep(1);
}
return NULL;
}
int main (int argc, char const *argv[])
{
pthread_t t1, t2;
int a = 2, b = 1;
pthread_create(&t1, NULL, f, &a);
pthread_create(&t2, NULL, f, &b);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return 0;
}
复制代码
程序运行的结果如下
~$ ./multiThread_staticVar
Thread ID = 3467, arg = 2, v = 1
Thread ID = 3467, arg = 2, v = 3
Thread ID = 3468, arg = 1, v = 1
Thread ID = 3468, arg = 1, v = 4
Thread ID = 3467, arg = 2, v = 6
Thread ID = 3468, arg = 1, v = 7
Thread ID = 3467, arg = 2, v = 9
Thread ID = 3468, arg = 1, v = 10
复制代码
可以看到,线程3467中static变量v被初始化为1,然后加上了2,变为3,然后sleep,线程3468开始执行,这时打印的v的值还是1,但执行
v += *(int *)arg;
复制代码
即v += 1;后v的值变为4,则v的值变化之前是3,即线程3467 sleep时的值,这里我不理解:当线程3468开始执行f()的时候,v的值应该已经是3,但打印出来是1,但执行
v += *(int *)arg;
复制代码
却变为4,这明明又是在线程3467的执行结果上加了1,为什么?还有,v是static变量,应该只初始化一次,但线程3468开始执行f()时v的值是1,即为其初始化的值,请各位朋友看看
多线程并发取数据竞争。
作者:
samlumengjun
时间:
2011-09-20 13:32
lz刚开始学多线程吧?最基本的同步问题,操作v的时候要加锁的。你的问题就是不加锁的关系。
作者:
edshea
时间:
2011-09-20 13:49
回复
2#
samlumengjun
你没有仔细看我的问题,我这里问的是static变量的初始化,不是加锁不加锁
作者:
samlumengjun
时间:
2011-09-20 13:56
回复
3#
edshea
你这个就是没加锁的问题,一开始创建的2个线程几乎是同时访问v的,所以都读到了初始值1,之后由于sleep的存在,就正常了,简单点验证一下,你就在第一和第二个线程创建函数中间加个sleep就明白了,或者就干脆在线程函数里读写v的时候加锁。
作者:
edshea
时间:
2011-09-20 14:42
回复
4#
samlumengjun
果然是这样,多谢!
我想看看多线程环境中的static变量的初始化,现在看来,多线程环境下static变量仍然只初始化一次,但这个是怎么做到的呢?
static变量被第一个线程初始化以后,第二个线程是如何知道这个static变量已被初始化的呢?
作者:
samlumengjun
时间:
2011-09-20 14:53
静态变量是在编译初始化的之后仅仅是访问或者修改。
作者:
edshea
时间:
2011-09-20 14:54
回复
6#
samlumengjun
全局变量和静态变量的初始化都是编译期就完成,明白了,多谢
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2