关于临界区的问题

Narvik 2013-08-02 11:28:33
#include  <windows.h>
#include <iostream.h>

DWORD WINAPI Fun1Proc( LPVOID lpParameter );

DWORD WINAPI Fun2Proc( LPVOID lpParameter );

int tickets=100;
CRITICAL_SECTION g_cs;

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);

InitializeCriticalSection(&g_cs);
Sleep(4000);
DeleteCriticalSection(&g_cs);

}

DWORD WINAPI Fun1Proc( LPVOID lpParameter )
{
while(TRUE)
{

try{
EnterCriticalSection(&g_cs);
Sleep(1);
if(tickets>0)
{
Sleep(1);
cout<<"Thread1 sell ticket : "<<tickets--<<endl;
LeaveCriticalSection(&g_cs);

}
else
{
LeaveCriticalSection(&g_cs);
break;
}
}
catch(...)
{

}

}
return 0;
}


DWORD WINAPI Fun2Proc( LPVOID lpParameter )
{
while(TRUE)
{

try{
EnterCriticalSection(&g_cs);
Sleep(1);
if(tickets>0)
{
Sleep(1);
cout<<"Thread2 sell ticket : "<<tickets--<<endl;
LeaveCriticalSection(&g_cs);

}
else
{
LeaveCriticalSection(&g_cs);
break;
}
}
catch(...)
{

}

}
return 0;
}



在上述代码中,程序并没有实现交替输出的功能,请问为什么? 还有 在程序中去掉try和catch后调试,会显示
First-chance exception in Critical.exe (NTDLL.DLL): 0xC0000005: Access Violation 请问这个错误如何解决,还有为什么try和catch会忽略这个错误。
...全文
729 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
蓝兔先生 2014-02-19
  • 打赏
  • 举报
回复
初始化临界区的位置错了。当主函数里面创建完线程后,子线程已经开始运行, 而此时主线程的指令未必执行到了初始化临界区的部分。这样你程序的未知率会提高。
lewisliulixin 2014-02-18
  • 打赏
  • 举报
回复
CreatThread之后 主线程不等待子线程结束 你就closehandle 合适吗
china_jeffery 2013-09-18
  • 打赏
  • 举报
回复
    hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);     hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL); 语句以后线程已经开执行了,然后你才初始化临界区,晚了点。 还有Sleep(1)木有意义,Sleep()根本无法精确到1ms。 其他的逻辑部分我就没看了。
modyaj 2013-09-18
  • 打赏
  • 举报
回复
用核心编程上的说法 临界区就是飞机上的厕所 进了厕所的人 可以在里上几次都没问题 所以 临界区只是用于资源访问控制 而不是同步 推荐楼主看看 这位仁兄的博客 应该就清楚了 http://blog.csdn.net/morewindows/article/details/7442639
xiaohutushen30 2013-08-11
  • 打赏
  • 举报
回复
用事件可以完成你要的效果!
Kaile 2013-08-11
  • 打赏
  • 举报
回复
用条件变量也可以
woshinia 2013-08-07
  • 打赏
  • 举报
回复
EnterCriticalSection(&g_cs);临界区不能保证2个线程执行的顺序的吧,临界区主要用来防止资源被同时访问。要严格控制执行顺序,用Event呗。
zxwangyun 2013-08-03
  • 打赏
  • 举报
回复
哥们 你一直纠结在这个问题上干嘛。本来线程就是由操作系统调度的,哪个线程被调度是随机的。 你一定要让两个线程交替运行的话,可使用一个变量来标示上一次调度的是哪个线程,如果上次调度的线程是本线程,sleep一下不就行了?
schlafenhamster 2013-08-02
  • 打赏
  • 举报
回复
两个线程,轮流使用临界区。 没错。 问题是 操作系统 并不是 两个线程 轮流 调度 ! 它 喜欢调度 那个 就那个, 这个 调度 与 临界区 毫无 关系。
孤必有邻 2013-08-02
  • 打赏
  • 举报
回复
两个线程,排队进入临界区,Sleep(1)使等待时间足够长,必然出现你一次我一次,严格的交替。 在VC中调试程序时,Output窗口有时会出现“First-chance exception in xxx.exe...”这样的信息。一般来说,这是由于程序中发生了异常,被VC捕获而产生的输出。 在调试器中运行程序时,如果程序产生异常,调试器会首先获得通知(即First-chance exception),而后此异常由产生它的程序负责捕获。如果程序没有捕获此异常,那么调试器会再次被通知(即Second-chance exception,Last-chance exception),并结束程序。 通常见到的“First-chance exception”一般是“0xC0000005: Access Violation”,“0xC00000FD: Stack Overflow”等,这些都说明程序中有缺陷,需要修正。 但是也有一些属于正常的情况,例如“First-chance exception in xxx.exe (KERNEL32.DLL): 0xE06D7363: Microsoft C++ Exception”。Windows 操作系统中广泛使用了结构化异常(SEH)来处理特殊情况,许多和底层打交道的API都靠SEH来处理可能发生的意外。并且,这些API中都有捕获SEH的代码,产生的异常不会对程序造成影响。但是由于上面提到的“First-chance exception,Second-chance exception”机制,VC仍然会有输出,但是我们完全可以忽略。如果你实在不喜欢这些输出信息,那你就必须禁用对特定异常的“First-chance exception”捕获。
schlafenhamster 2013-08-02
  • 打赏
  • 举报
回复
schlafenhamster 2013-08-02
  • 打赏
  • 举报
回复



volatile int tickets=1000;

while((tickets%2)==1)
{
LeaveCriticalSection(&g_cs);
cout<< "Wait Thread2 to be scheduled" <<endl;
Sleep(0);
EnterCriticalSection(&g_cs);
}

在 本程序运行时,打开 网页。
zxwangyun 2013-08-02
  • 打赏
  • 举报
回复
引用 5 楼 schlafenhamster 的回复:
“还有 在程序中去掉try和catch后调试,会显示。。。” InitializeCriticalSection(&g_cs); 要放在 创建线程 前 (或者 先 Suspend ,最后 Resume)
同意
schlafenhamster 2013-08-02
  • 打赏
  • 举报
回复
给你改了改:

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

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

volatile int tickets=100;
CRITICAL_SECTION g_cs;

void main()
{
	HANDLE hThread1;
	HANDLE hThread2;
	InitializeCriticalSection(&g_cs);
	hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
	hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
	while(tickets >0);
	CloseHandle(hThread1);
	CloseHandle(hThread2);
	DeleteCriticalSection(&g_cs);
}

DWORD WINAPI Fun1Proc( LPVOID lpParameter )
{
	while(TRUE)
	{
		EnterCriticalSection(&g_cs);
		if(tickets>0)
		{
			tickets --;
			cout<<"Thread1 sell ticket : "<<tickets <<endl;
		}
		while((tickets%2)==1)
		{
			LeaveCriticalSection(&g_cs);
			Sleep(0);
			EnterCriticalSection(&g_cs);
		}
		LeaveCriticalSection(&g_cs);
	}
	return 0;
}


DWORD WINAPI Fun2Proc( LPVOID lpParameter )
{
	while(TRUE)
	{
		EnterCriticalSection(&g_cs);
		if(tickets>0)
		{
			tickets --;
			cout<<"Thread2 sell ticket : "<< tickets <<endl;
		}
		while((tickets%2)==0)
		{
			LeaveCriticalSection(&g_cs);
			Sleep(0);
			EnterCriticalSection(&g_cs);
		}
		LeaveCriticalSection(&g_cs);
	}
	return 0;
}
schlafenhamster 2013-08-02
  • 打赏
  • 举报
回复
“我想问下用临界区,无法实现线程1和线程2交替执行?” 基本上 没法, 如果 你 脑瓜里 有 操作系统 的 话,那么 就 要 考虑 操作系统 可以 在 一个线程的 任何一条语句 中 停止 该 线程 的 运行。 也可以 反复 调用 该 线程。 你要 实现你的 想法, 在2个线程中 都要 回答 这样一个问题:“另一个线程,是不是已经被调度运行一次” 如果 是,就进入 你的 想法, 如果 不是 就 放弃这次运行。
Narvik 2013-08-02
  • 打赏
  • 举报
回复
引用 10 楼 schlafenhamster 的回复:
“还有为什么try和catch会忽略这个错误。” try 和 catch 是 C++ 的 不是 SEH ,要 打开 C++ 的 设置。 另外 Fun1Proc 的 catch 怎么 在 while 外 ?
是在while内的,可能是我格式没有对齐。我想问下用临界区,无法实现线程1和线程2交替执行?
schlafenhamster 2013-08-02
  • 打赏
  • 举报
回复
“不过此时应该是主线程在运行吧,要等到sleep把主线程挂起以后,才调度子线程吧。” 想当然! CreateThread 文档 并没有 说 等待。 只有 suspend 才 会 等待到 resume。
schlafenhamster 2013-08-02
  • 打赏
  • 举报
回复
“还有为什么try和catch会忽略这个错误。” try 和 catch 是 C++ 的 不是 SEH ,要 打开 C++ 的 设置。 另外 Fun1Proc 的 catch 怎么 在 while 外 ?
Narvik 2013-08-02
  • 打赏
  • 举报
回复
引用 8 楼 schlafenhamster 的回复:
”放在线程创建的后面有什么不适吗,“ 可是线程 已经 在 执行了。 (或者 线程创建时先 Suspend ,初始化临界区后,再 Resume)
不过此时应该是主线程在运行吧,要等到sleep把主线程挂起以后,才调度子线程吧。
schlafenhamster 2013-08-02
  • 打赏
  • 举报
回复
”放在线程创建的后面有什么不适吗,“ 可是线程 已经 在 执行了。 (或者 线程创建时先 Suspend ,初始化临界区后,再 Resume)
加载更多回复(5)

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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