Chinaunix

标题: 多线程环境中的static变量问题【已解决】 [打印本页]

作者: edshea    时间: 2011-09-20 12:51
标题: 多线程环境中的static变量问题【已解决】
本帖最后由 crazyhadoop 于 2011-09-20 18:13 编辑

以前被问过一个多线程环境中的static变量问题,到现在一直没搞明白,
今天写了一小段代码,但解释不清,大家帮忙看看吧
multiThread_staticVar.c
  1. #include <stdio.h>                                                               
  2. #include <pthread.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/syscall.h>

  6. #define INIT 1
  7. #define MAX 10

  8. //static int v = INIT;

  9. void *f (void *arg)
  10. {
  11.   static int v = INIT;
  12.   printf("Thread ID = %ld, arg = %d, v = %d\n", syscall(SYS_gettid), *(int *)arg, v);

  13.   while (v < MAX) {
  14.     v += *(int *)arg;
  15. //    printf("v = %d\n", v);
  16.     printf("Thread ID = %ld, arg = %d, v = %d\n", syscall(SYS_gettid), *(int *)arg, v);
  17.     sleep(1);
  18.   }

  19.   return NULL;
  20. }

  21. int main (int argc, char const *argv[])
  22. {
  23.   pthread_t t1, t2;
  24.   int a = 2, b = 1;
  25.   pthread_create(&t1, NULL, f, &a);
  26.   pthread_create(&t2, NULL, f, &b);

  27.   pthread_join(t1, NULL);
  28.   pthread_join(t2, NULL);

  29.   return 0;
  30. }
复制代码
程序运行的结果如下
  1. ~$ ./multiThread_staticVar
  2. Thread ID = 3467, arg = 2, v = 1
  3. Thread ID = 3467, arg = 2, v = 3
  4. Thread ID = 3468, arg = 1, v = 1
  5. Thread ID = 3468, arg = 1, v = 4
  6. Thread ID = 3467, arg = 2, v = 6
  7. Thread ID = 3468, arg = 1, v = 7
  8. Thread ID = 3467, arg = 2, v = 9
  9. Thread ID = 3468, arg = 1, v = 10
复制代码
可以看到,线程3467中static变量v被初始化为1,然后加上了2,变为3,然后sleep,线程3468开始执行,这时打印的v的值还是1,但执行
  1. v += *(int *)arg;
复制代码
即v += 1;后v的值变为4,则v的值变化之前是3,即线程3467 sleep时的值,这里我不理解:当线程3468开始执行f()的时候,v的值应该已经是3,但打印出来是1,但执行
  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