双CPU,多线程同步问题,大虾请进!

aa335418265 2012-09-27 11:21:21
当我们使用内核对象(如事件内核对象)进行2线程同步的时候,是否会发生如下情况:
两个线程都是第一次启动时候,同时获取到内核对象的使用权?我觉得会发生,上代码:

#include <windows.h>
#include <iostream.h>

DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);

int tickets=100;
HANDLE g_hEvent;
void main()
{
HANDLE hThread1;
HANDLE hThread2;
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);

g_hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
SetEvent(g_hEvent);

Sleep(4000);
}


DWORD WINAPI Fun1Proc(
LPVOID lpParameter
)
{


while(TRUE)
{ //Sleep(10); 不加此行代码时候,结果经常会出现 :
//thread2 sell ticket 100
//thread1 sell ticket 99
WaitForSingleObject(g_hEvent,INFINITE);

if(tickets>0)
{ Sleep(1);
cout<<"thread1 sell ticket :"<<tickets--<<endl;

}
else
break;

}

return 0;
}



DWORD WINAPI Fun2Proc(
LPVOID lpParameter
)
{
while(TRUE)
{ WaitForSingleObject(g_hEvent,INFINITE);

if(tickets>0)
{
cout<<"thread2 sell ticket :"<<tickets--<<endl;


}
else
break;


}

return 0;
}

结果有两种:
1) thread2 sell ticket :100

2) thread2 sell ticket :100
thread1 sell ticket :99

按照我的分析,出现结果2的原因为:因我的电脑是双CPU的,所以第一次两个线程可能同时都得到事件内核对象处于信号状态,于是两个线程都获取到了对WaitForSingleObject函数一下的代码的使用权,但是由于线程1的Sleep(1)的存在,所以线程2先完成了cout<<"thread2 sell ticket :"<<tickets--<<endl;这行代码的执行.所以线程2打印100,之后线程1睡眠过后,接着执行cout<<"thread1 sell ticket :"<<tickets--<<endl;这行代码.(因为是自动重置,所以内核对象会一直处于没信号状态,两个线程都不能接着打印!)

不知道我的分析对不对呢?我想问的是,在双CPU情况下,两个线程是否有可能都同时获取到信号?
...全文
259 7 打赏 收藏 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
fxworld 2012-09-28
  • 打赏
  • 举报
回复


二楼的分析比较到位,是楼主的程序逻辑(执行顺序)有问题,将CreateEvent函数放到创建线程的前面可以解决线程等待事件对象的问题。
BORLANDSUN 2012-09-28
  • 打赏
  • 举报
回复
我觉得不会,OS会把这个细节屏蔽掉。楼主试试在双核CPU上会不会也有这个问题。
aa335418265 2012-09-28
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
我觉得不会,OS会把这个细节屏蔽掉。楼主试试在双核CPU上会不会也有这个问题。
[/Quote]

我的就是双核CPU了,看看2楼的分析,我感觉有道理!
aa335418265 2012-09-28
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]
我给你分析一下

首先,你的两个子线程是非挂起创建,创建后两线程就开始执行了,
创建后os对你的进程至少3个线程开始调度,而你的Event对象这个时候还不知道在哪里,
WaitForSingleObject也没判断返回值,那么,会发生什么?
好吧,在你的event事件对象创建之前你线程中的WaitForSingleObject函数会返回失败,
当然,在你这代码里就是继续往下走并继续循环……
[/Quote]

分析的有道理,原来是这样的情况!谢谢了
aa335418265 2012-09-28
  • 打赏
  • 举报
回复
[Quote=引用楼主 的回复:]
当我们使用内核对象(如事件内核对象)进行2线程同步的时候,是否会发生如下情况:
两个线程都是第一次启动时候,同时获取到内核对象的使用权?我觉得会发生,上代码:

#include <windows.h>
#include <iostream.h>

DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD ……
[/Quote]


我的就是双核CPU了
dataxdata 2012-09-28
  • 打赏
  • 举报
回复
这种情况应该使用互斥量Mutex,而不是使用通知事件Event进行同步
yoke_wolf 2012-09-28
  • 打赏
  • 举报
回复
我给你分析一下

首先,你的两个子线程是非挂起创建,创建后两线程就开始执行了,
创建后os对你的进程至少3个线程开始调度,而你的Event对象这个时候还不知道在哪里,
WaitForSingleObject也没判断返回值,那么,会发生什么?
好吧,在你的event事件对象创建之前你线程中的WaitForSingleObject函数会返回失败,
当然,在你这代码里就是继续往下走并继续循环,输出内容,这个过程持续的你的event对象创建完成,
这个过程时间取决于硬件配置,速度,系统调度规则等等,
很显然,这个过程产生的输出是不可预调的

其次,我们再看你的事件对象的创建。你创建的是非管理重置,初始状态为无信号状态的event object,
所以,在前面说的那个过程结束,你的对象创建后,两线程会开始等待事件信号,直到你的SetEvent(g_hEvent)执行完成,此时,其中一个幸运的子线程将会得到事件信号,由于你的事件是非管理重置,你的event对象自动重置为无信号状态,该线程继续输出相关内容然后继续等待。当然,事件现在处于无信号状态,而你的程序再也没用SetEvent的调用发生,所以,直到你程序结束,再也没人能等到你的event信号了。

从上可知,你程序现在的结果是: 一系列不可预料的输出(包括可能什么都没有) + 某个幸运线程的一条输出 = 不可预料的输出


改下面两个步骤,你应该可以看到想要的结果, 至于为什么,说了那么多,应该可以想明白了
1.把
g_hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
放到
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
这一行前面

2. 在你两个线程循环中的break; 后面都加一行 SetEvent(g_hEvent);


你这问题是关于事件对象的,我就只说他们相关的,其他问题我就不说了
内容概要:本文围绕【复现IEEE二区文献】基于状态空间表示与组件连接法的构网型逆变器统一小信号建模框架研究,提出了一种适用于多控制策略构网型逆变器的小信号建模方法。该方法结合状态空间建模理论与组件连接法(Component Connection Method),实现了对复杂逆变器系统动态特性的精确描述,尤其适用于分析系统在不同运行工况下的稳定性。通过Matlab代码实现,构建了包含控制环路、滤波器、锁相环等关键模块的完整小信号模型,并利用特征值分析与模态参与度评估系统稳定性,解决了传统建模方法在面对多时间尺度、强耦合非线性控制结构时建模困难、精度不足的问题。研究还探讨了关键控制参数对系统稳定边界的影响,为构网型逆变器的参数整定与优化设计提供了理论依据和技术支撑。; 适合人群:具备电力电子、自动控制理论基础,从事新能源发电、微电网、电力系统稳定性研究的研究生、科研人员及工程技术人员,尤其适合致力于高水平期刊论文复现与仿真实践的科研工作者。; 使用场景及目标:① 掌握构网型逆变器统一小信号建模的核心方法,复现IEEE二区高水平文献成果;② 理解状态空间法与组件连接法在复杂电力电子系统建模中的集成应用;③ 利用Matlab进行特征值分析与稳定性判据研究,支撑科研仿真与论文写作;④ 为多逆变器并联系统、微电网稳定性分析等课题提供建模工具与技术路线参考。; 阅读建议:建议读者结合Matlab代码与文中建模流程逐步调试,重点关注各子模块状态方程的推导与系统整体矩阵组装过程,深入理解控制参数对系统极点分布的影响规律,建议配合其他稳定性分析案例进行对比学习以加深理解。

1,317

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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