多线程操作一个全局变量的一致性问题

cppkiller 2004-12-13 03:32:34
有一个实验,是用多线程操作一个全局变量。
我们看资料,都知道全局变量在多线程的操作下,应该使用TCriticalSection来保证一次只有一个线程操作它。
我的问题是这样的:

在主单元的h文件里放一个
int a=1;
这样,就是个全局变量。主单元另外一处(保证先执行到)将其赋值成2 :
a=2;

另外一个unit文件,设计一个简单的线程:

在h文件里:

class o2 : public TThread
{
private:
protected:
void __fastcall Execute();
public:
__fastcall o2(bool CreateSuspended);
};

在cpp文件里:

__fastcall o2::o2(bool CreateSuspended)
: TThread(CreateSuspended)
{
CreateSuspended=true;
}
//---------------------------------------------------------------------------
void __fastcall o2::Execute()
{
//---- Place thread code here ----
CS->Acquire();
if(a==2)
a=9;
if(a==1)
a=10;
CS->Release();
}

回到主单元unit1,这样调用这个线程对象:
o2 *oo=new o2(true);
....
void __fastcall TForm1::Button4Click(TObject *Sender)
{
oo->Resume();
if(a==9)
{
ShowMessage("now a=9 ");

};
if(a==10)
{
ShowMessage("now a=10 ");

}
}
//======================
现在的问题是,象这个例子这样使用线程将那个全局变量a进行改变,即使在debug工具里可以看到a=2,但在线程对象oo里,仍然认为它是1。

这是一个有意思的现象。请大侠们指点迷津。应该如何才能保证多线程条件下数据的一致。
...全文
1231 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
sydt2000 2005-05-18
  • 打赏
  • 举报
回复
向 :CCED136(夜林箭) 同志学习!!!
sydt2000 2005-05-18
  • 打赏
  • 举报
回复
顶一下!
FrankZYZ 2005-02-04
  • 打赏
  • 举报
回复
顶一下
cppkiller 2005-02-03
  • 打赏
  • 举报
回复
cced136的批判很好!

他后面那个长回复很不错,特别感谢!但他前面那个帖子也正显示了CSDN上很多人的共同特性:搞懂了的人摆架子(“自己看书去!”)卖关子(“你的方法不对,但你先自己想想,我不马上告诉你”)或懒得回复,典型!
CSDN上还有另外一种典型:提问的人不把问题提清楚,简单得如同懒堕,比如:“我明天就要被炒鱿鱼了,大家帮忙解决一个问题吧:两个线程不同步怎么办?”
我自己解决了这个问题,是经过一通胡乱调整,将放到h文件里的那个int a=1;改到了cpp文件里,只有一个主单元文件,一个线程单元文件(装了多个线程)。并使用指针传递a的引用给线程,不仅要使用TCriticalSection。
由于在线程的构造函数里有 int* 型的参数,可以在主单元里初始化那个线程时,将a的引用传入,可保证对a的操作是一致的,否则,线程在声明和定义时并不知道那个a的存在,容易出错,在同一主单元里初始化时传入的指针可以保证对同一int a进行操作。

cced136的回复,使我更深入理解了那个h文件和cpp文件的关系,我仔细珍藏了,作为对h文件、多单元文件时,全局变量使用的指导。
CCED136这样的回复是很有价值的,csdn 应该大力提倡,这也是我回复帖子时的榜样。

我们在borland的新闻组里讨论问题时,TeamB的人或其他朋友都非常认真地进行回复,太感动人了,雷锋精神在国外得到了发扬光大啊。
tomlance 2005-02-01
  • 打赏
  • 举报
回复
线程单元不用include "unit1.h",直接用extern int a;声明就可以了
lihao1111111111 2005-01-31
  • 打赏
  • 举报
回复
CCED136说的很对!
cppkiller 2005-01-29
  • 打赏
  • 举报
回复
希望大家继续批判!
cchao 2005-01-29
  • 打赏
  • 举报
回复
mk
CCED136 2005-01-28
  • 打赏
  • 举报
回复
在楼主这样的情况中,定义全局变量时,不能像楼主这样定义:

“在主单元的h文件里放一个int a=1;这样,就是个全局变量。”

正确的定义方法应该为(假设单元文件为 Unit1.Cpp/Unit1.h):
在 Unit1.Cpp 中定义如下:
int a=1;

在 Unit1.h 中申明如下:
extern int a;

其他 Unit 单元需要使用时,直接 Include 文件 Unit1.h 即可。
如果是多个线程都需要全局变量 a 时,则使用TCriticalSection
来进行同步就可以了。绝对不会出现楼主说的情况:

“现在的问题是,象这个例子这样使用线程将那个全局变量a进行改变,
即使在debug工具里可以看到a=2,但在线程对象oo里,仍然认为它是1。
这是一个有意思的现象。请大侠们指点迷津。应该如何才能保证多线程
条件下数据的一致。”。

我再解释一下原因:
如果直接在 .h 文件中定义 int a=1;

此时, a 确实是全局变量(单元文件内的全局属性),但是,每一个包含了
该 .h 文件的 .cpp 单元都将为自己生成一个 a 变量的实例。

举例来说:现在 int a=1;定义在 Unit1.h 文件中,同时 Unit1.cpp 文件以
及Unit2.cpp 文件都包含了(Include) Unit1.h 文件,则此时的情况是: Unit1
单元独立拥有一个 a 变量的实例, Unit2 单元也拥有一个独立的 a 变量的实例。
Unit1 以及 Unit2 单元在操作 a 变量的时候,都是操作的各自拥有的 a 变量。所
以才会出现楼主说的:在线程中改变了 a 的值,但其他单元 a 的数值仍然没有被
改变。


CCED136 2005-01-28
  • 打赏
  • 举报
回复
今天周末,我要早点回家看我的宝宝,本来想让楼主好好想想的,

我看还是算了。还是我直接说出来算了。
CCED136 2005-01-28
  • 打赏
  • 举报
回复
呵呵,真有意思。

按照楼主顶楼的方法设置多个单元文件共享的全局变量,

根本就是错误的!!不出错误才是怪事,楼主还说自己

已经解决了。照我看,楼主还是没有明白错在哪个地方。

土著巫师 2005-01-28
  • 打赏
  • 举报
回复
1、

if(a==2) a=9;
if(a==1) a=10;

假如数据为2,被赋值为9,后面的句子就没必要存在了。我想应这样写
if(a==2) a=9;
else if(a==1) a=10;

2、另外,主线程里Button4Click里要读取值也要用临界区,否则值不定。

bjnw 2005-01-28
  • 打赏
  • 举报
回复
你也真是够意思
cppkiller 2005-01-14
  • 打赏
  • 举报
回复
ZengMuAnSha(曾牧暗鲨) :
我是气愤有些csdn里面的网友,发了问题,人家帮忙一阵,结果自己搞掂了,最多回复一下:

“谢谢,我已经搞掂”。

所以,我就也这样来一下,展览一下。供大家批判。
  • 打赏
  • 举报
回复
那你也要公布下你的搞定的方法呀?
cppkiller 2005-01-06
  • 打赏
  • 举报
回复
自己搞掂了。
在构造函数里,传指针参数。
tsk 2004-12-20
  • 打赏
  • 举报
回复
帮你想想看....
cppkiller 2004-12-20
  • 打赏
  • 举报
回复
无人响应?自己顶一下。
BigFatBear 2004-12-16
  • 打赏
  • 举报
回复
封装三个对a进行操作的函数,一个是读取,一个是赋值,一个是改变(增减等等);
每个操作的模式大概为
procedure xx()
{
P(s);
// 函数的操作;
V(s);
}
用信号量或者临界区都行
其他地方的操作都调用这三个函数




lihongxing2002 2004-12-14
  • 打赏
  • 举报
回复
up

1,221

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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