难道我对volatile关键字的理解以前都是错误的?

此帐号已弃用12 2012-07-11 06:03:43
请看代码

volatile int tickets=0;
volatile BOOL g_bRun = TRUE;
DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
char buf[100];
while(g_bRun)
{
if(tickets<10)
{
sprintf(buf,"\nthread1 sell ticket = %d",tickets);
OutputDebugString(buf);
printf(buf);
tickets++;
}
else
Sleep(10);
}
return 0;
}

DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
char buf[100];
while(g_bRun)
{
if(tickets<10)
{
sprintf(buf,"\nthread2 sell ticket = %d",tickets);
OutputDebugString(buf);
printf(buf);
tickets++;
}
else
Sleep(10);
}
return 0;
}

int main(int argc, char* argv[])
{
CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
Sleep(2000);
system("PAUSE");
g_bRun = FALSE;
return 0;
}


理论上输出应该是

thread2 sell ticket = 0
thread1 sell ticket = 1
thread2 sell ticket = 2
thread1 sell ticket = 3
thread2 sell ticket = 4
thread1 sell ticket = 5
thread2 sell ticket = 6
thread1 sell ticket = 7
thread2 sell ticket = 8
thread1 sell ticket = 9


实际上却是这样

thread1 sell ticket = 0
thread1 sell ticket = 0
thread2 sell ticket = 0
thread1 sell ticket = 1
thread2 sell ticket = 2
thread1 sell ticket = 3
thread2 sell ticket = 4
thread1 sell ticket = 5
thread2 sell ticket = 6
thread1 sell ticket = 7
thread2 sell ticket = 8
thread1 sell ticket = 9

最奇怪的地方是
thread1 sell ticket = 0
thread1 sell ticket = 0
请高手解惑
...全文
243 5 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
AnYidan 2012-07-12
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

引用 2 楼 的回复:

volatile 不是用来做临界区的。
而是告知编译器这个符号是易变的。
这样编译器就会假定她使用之间需要检测这个易变性。
比如,需要重新读取,或者不对与之关联的语句进行调整顺序等优化。

我用 volatile 的很大原因就是可以保证因果关系。


++
说得不错。
[/Quote]


++
FrankHB1989 2012-07-12
  • 打赏
  • 举报
回复
volatile本来就不是给你拿来做线程同步的。
volatile显式要求lvalue conversion时从对象存储的内存的取值,而非之前取到过的(例如放在cache里的)值。对于一些底层操作,如映射硬件存储,中断处理等场合是必要的。至于多线程,用volatile是有可能解决【一小部分】一致性问题,但会严重阻碍优化。
pathuang68 2012-07-11
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

volatile 不是用来做临界区的。
而是告知编译器这个符号是易变的。
这样编译器就会假定她使用之间需要检测这个易变性。
比如,需要重新读取,或者不对与之关联的语句进行调整顺序等优化。

我用 volatile 的很大原因就是可以保证因果关系。
[/Quote]

++
说得不错。
Saleayas 2012-07-11
  • 打赏
  • 举报
回复
volatile 不是用来做临界区的。
而是告知编译器这个符号是易变的。
这样编译器就会假定她使用之间需要检测这个易变性。
比如,需要重新读取,或者不对与之关联的语句进行调整顺序等优化。

我用 volatile 的很大原因就是可以保证因果关系。
baichi4141 2012-07-11
  • 打赏
  • 举报
回复
当两个线程同时输出字符串时,会有什么结果?
别以为只有变量需要线程安全,一切“唯一”的东西都需要保证线程安全,包括输出

70,020

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧