qt 作用域 数据库_VC知识库BLOG-局部变量的作用域-多线程和函数里的静态变量

试试下面这段代码的输出是什么?

#include

#include

#include

class foo

{

public:

foo()

{

printf( "before sleep\n" );

Sleep( 1000 );

printf( "after sleep\n" );

}

void test()

{

printf( "in test\n" );

}

};

foo* bar()

{

static foo a;

return &a;

}

unsigned __stdcall thread( void* )

{

foo* p = bar();

p->test();

return 0;

}

int _cdecl main( int argc, char** argv )

{

for( int i = 0; i < 10; ++i )

{

uintptr_t t = _beginthreadex( NULL, 0, thread, NULL, 0, NULL );

CloseHandle( (HANDLE)t );

}

Sleep( 5000 );

return 0;

}

不知道C/C++标准有什么规定没有, 但粗看起来好像是编译器的问题呀。我用的是vc8,谁帮忙测测别的编译器。

根据星星的建议,把输出贴出来,如下:

before sleep

in test

in test

in test

in test

in test

in test

in test

in test

in test

after sleep

in test

这里的问题是至少有10个中的9个线程没有等对象初始化完成,就已经调用对象的方法了,这肯定是不对的。我大概看了一下反汇编的结果,实际上还可能出现构造函数被调用多次的情况。

要解决这个问题,在编译器的层次上要容易一点。如果是在用户程序的层次上,则麻烦的多,因为这类方法都会涉及到另一个静态变量的初始化。

posted on 2008-05-29 09:33 局部变量 阅读(2077)

re: 多线程和函数里的静态变量

2008-05-29 17:46

因为多线程你莫有同步。。。

class CCriticalSection

{

public:

CCriticalSection() { ::InitializeCriticalSection( &m_cs ); }

~CCriticalSection() { ::DeleteCriticalSection( &m_cs ); }

void Lock() { ::EnterCriticalSection( &m_cs ); }

void Unlock() { ::LeaveCriticalSection( &m_cs ); }

private:

CRITICAL_SECTION m_cs;

};

CCriticalSection cs;

class foo

{

public:

foo()

{

printf( "before sleep\n" );

Sleep( 3000 );

printf( "after sleep\n" );

}

void test()

{

printf( "in test\n" );

}

};

foo* bar()

{

cs.Lock();

static foo a;

cs.Unlock();

return &a;

}

unsigned __stdcall thread( void* )

{

foo* p = bar();

p->test();

return 0;

}

int _cdecl main( int argc, char** argv )

{

for( int i = 0; i     {

uintptr_t t = _beginthreadex( NULL, 0, thread, NULL, 0, NULL );

CloseHandle( (HANDLE)t );

}

Sleep( 5000 );

return 0;

}

re: 多线程和函数里的静态变量

2008-05-29 17:49

锁是放在 bar() 中好?还是 thread() 中好?

to bl: 你的方法是错的

2008-05-29 20:01

我在最后已经说了“

如果是在用户程序的层次上,则麻烦的多,因为这类方法都会涉及到另一个静态变量的初始化” 。所以常见的多线程同步方式在这里都会失效。

你的问题是无法保证临界区先于对象初始化,虽然也许在这个例子中确实是它先初始化的。

re: 多线程和函数里的静态变量

2008-05-29 21:15

倒。。。....那临界区先于线程就可以了。。。

re: 多线程和函数里的静态变量

2008-05-29 21:23

这个例子很好的说明了,这种形式的单件的缺点就是构造的时候线程不安全

to heroboy

2008-05-30 09:02

握手, 这个例子正是我在考虑单件的问题时想到的, 其实单件还有几个其它问题, 打算过几天全写出来。

to 玻璃小屋:

“临界区先于线程就可以了”,在这个例子中是这样。但在实际项目中只保证这一点是不够的,必须保证临界区先于对象, 否则就可能在临界区初始化之前Enter它了。

据我所知,用户程序中要保证临界区先初始化,只能靠#pragma init_seg,但我想多数C++程序员根本不知道这个选项

re: 多线程和函数里的静态变量

2008-05-30 10:41

其实,构造函数到汇编这层后 就是一普通函数,他有可能被不同线程执行。。。 而所谓的单件 就是一全局部变量~  临界区也是全局的~ 全局的东西被构造出来之后,才能轮到 程序执行。。也就是线程执行。。。

所以说。。我认为你这样还是 对 全局部变量 进行多线程访问同步控制的问题 -.-!

re: 多线程和静态变量

2008-06-03 11:58

我觉得输出很正常啊,甚至输出乱码都有可能。

函数里的static 变量,在函数第一次调用时初始化,程序退出时析构(函数间的内部static变量析构顺序是不确定的)。

re: 多线程和静态变量

2008-06-03 12:03

不好意思,明白你的意思了。不过,我觉得编译器视乎也很难对你的static foo a;进行保护,他未必知道你要多线程使用bar函数。他要是随便多线程保护掉,那么性能上会有损失。最关键的是,这本来是用户层是否多线程事,编译器来做似乎不太合理。

to 清风雨

2008-06-03 13:40

对于vc来说,如果我用多线程运行时库, 它就应该保护。否则可以不保护。我想到了一种实现方法,代价根本不高.

re: 多线程和函数里的静态变量

2008-06-04 22:15

代价不高,也是有代价的。不符合C++的精神:你不需要为你不使用的东西付出代价。

这个例子,直接在线程启动前调用一下bar(),就什么问题都解决了,也不需要什么同步了

to 小明

2008-06-05 08:39

你的做法恰恰违反了c++的精神, 如果程序的某次运行根本不需要调用bar(),那我的做法没有为不使用的东西付出代价,而你的付出了.

re: 多线程和函数里的静态变量

2008-06-05 12:20

C++ 只是编译器的C++。。。运行期没有C++ 只有面向过程。。。

to boli

2008-06-05 12:50

刚才讨论的已经超出语言的范畴了:)

不过小明的另外一个问题是:不付出代价是有前提的,这个前提是“正确”,错误的做法再“廉价”也没有用

re: 多线程和函数里的静态变量

2008-06-05 17:54

靠,都説些啥啊,静态变量本身都只初始化一次,还扯出多线程的问题!郁闷!

re: 多线程和函数里的静态变量

2008-06-06 16:08

ls,多线程的问题会造成静态变量被初始化多次的。

--------------------next---------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值