当前位置: 首页 > article >正文

C语言中,事件对象(CreateEvent)、互斥对象(CreateMutex)、关键代码段(InitializeCriticalSection)

 事件对象(CreateEvent)、互斥对象(CreateMutex)、关键代码段(InitializeCriticalSection)都是保证数据安全的一些措施。

1、互斥对象和事件对象属于内核对象,利用内核对象进行线程同步,速度较慢,但可以实现在多个进程中各线程间进行同步。

2、关键代码段式工作在用户方式下,同步速度较快,但在使用关键代码段时,很容易进入死锁状态,因为在进入关键代码时无法设定超时值。

     MFC下InitializeCriticalSection()和DeleteCriticalSection()可以放在类的构造函数和析构函数中

 

CreateEvent

代码实例1.1 Event

#include "stdafx.h"  
#include <iostream>  
#include <windows.h>  using namespace std;  DWORD WINAPI thread1fun(LPVOID);  
DWORD WINAPI thread2fun(LPVOID);  int tickets=20;  
HANDLE hEvent;  int main()  
{  HANDLE hthread1,hthread2;  the third parameter: 指定事件对象的初始状态。  /// 如果为TRUE,初始状态为有信号状态; FALSE:为无信号状态。  /// the second parameter: TRUE:人工重置,否则自动重置无信号状态  hEvent=CreateEvent(NULL,FALSE,FALSE,_T("tickets"));    if(hEvent)  {  if(ERROR_ALREADY_EXISTS==GetLastError()) //当前有实例在  {  cout<<"only instance can run\n";  }  }  SetEvent(hEvent);  ///set 有信号状态  hthread1=CreateThread(NULL,0,thread1fun,NULL,0,NULL);  //  Sleep(11);  hthread2=CreateThread(NULL,0,thread2fun,NULL,0,NULL);  //  while(1)  Sleep(10000);  CloseHandle(hthread1);//关闭句柄并不终止程序  CloseHandle(hthread2);  CloseHandle(hEvent);  return 0;  
}  DWORD WINAPI thread1fun(LPVOID lpParameter)  
{  while(1)  {   ///请求到信号,系统自动重置为无信号状态  WaitForSingleObject(hEvent,INFINITE);    if(tickets>0)  {  cout<<"thread 1: "<<tickets--<<endl;  Sleep(50);  }  else  break;  SetEvent(hEvent);  //set 有信号状态  }  return 0;  
}  DWORD WINAPI thread2fun(LPVOID lpParameter)  
{  while(1)  {  WaitForSingleObject(hEvent,INFINITE); /请求到信号,系统重置为无信号状态  if(tickets>0)  {  cout<<"thread 2: "<<tickets--<<endl;  Sleep(10);  }  else  break;  SetEvent(hEvent);  set 有信号状态  }  return 0;  
}  

执行结果:

 

 

代码实例1.2 无 Event 

#include "stdafx.h"  
#include <iostream>  
#include <windows.h>  using namespace std;  DWORD WINAPI thread1fun(LPVOID);  
DWORD WINAPI thread2fun(LPVOID);  int tickets=20;  
HANDLE hEvent;  int main()  
{  HANDLE hthread1,hthread2;  the third parameter: 指定事件对象的初始状态。  /// 如果为TRUE,初始状态为有信号状态; FALSE:为无信号状态。  /// the second parameter: TRUE:人工重置,否则自动重置无信号状态  //hEvent=CreateEvent(NULL,FALSE,FALSE,_T("tickets"));    //if(hEvent)  {  if(ERROR_ALREADY_EXISTS==GetLastError()) //当前有实例在  {  cout<<"only instance can run\n";  }  }  //SetEvent(hEvent);  ///set 有信号状态  hthread1=CreateThread(NULL,0,thread1fun,NULL,0,NULL);  //  Sleep(11);  hthread2=CreateThread(NULL,0,thread2fun,NULL,0,NULL);  //  while(1)  Sleep(10000);  CloseHandle(hthread1);  CloseHandle(hthread2);  CloseHandle(hEvent);  return 0;  
}  DWORD WINAPI thread1fun(LPVOID lpParameter)  
{  while(1)  {   ///请求到信号,系统自动重置为无信号状态  //WaitForSingleObject(hEvent,INFINITE);    if(tickets>0)  {  cout<<"thread 1: "<<tickets--<<endl;  Sleep(30);  }  else  break;  //SetEvent(hEvent);  //set 有信号状态  }  return 0;  
}  DWORD WINAPI thread2fun(LPVOID lpParameter)  
{  while(1)  {  //WaitForSingleObject(hEvent,INFINITE); /请求到信号,系统重置为无信号状态  if(tickets>0)  {  cout<<"thread 2: "<<tickets--<<endl;  Sleep(10);  }  else  break;  //SetEvent(hEvent);  set 有信号状态  }  return 0;  
}  

 

 

 

代码实例 2.1 有 Mutex

#include "StdAfx.h"  
#include <iostream>  
#include <windows.h>  using namespace std;  DWORD WINAPI thread1fun(LPVOID);  
DWORD WINAPI thread2fun(LPVOID);  int tickets=20;  
HANDLE hMutex;  int main()  
{  HANDLE hthread1,hthread2;  hMutex=CreateMutex(NULL,FALSE,_T("tickets"));  ///TRUE :main thread got mutex object  hthread1=CreateThread(NULL,0,thread1fun,NULL,0,NULL);  hthread2=CreateThread(NULL,0,thread2fun,NULL,0,NULL);  CloseHandle(hthread1);  CloseHandle(hthread2);  if(hMutex)  {  if(ERROR_ALREADY_EXISTS==GetLastError())  {  cout<<"only instance can run!"<<endl;  return 0;  }  }  Sleep(10000);  return 0;  
}  DWORD WINAPI thread1fun(LPVOID lpParameter)  
{  while(1)  {  WaitForSingleObject(hMutex,INFINITE);  if(tickets>0)  {  Sleep(30);  cout<<"thread 1: "<<tickets--<<endl;  }  else  break;  ReleaseMutex(hMutex);  //释放当前线程ID,互斥对象计数器-1  }  //谁拥有互斥对象,你可以释放  return 0;  
}  DWORD WINAPI thread2fun(LPVOID lpParameter)  
{  while(1)  {  WaitForSingleObject(hMutex,INFINITE);  if(tickets>0)  {  Sleep(10);  cout<<"thread 2: "<<tickets--<<endl;  }  else  break;  ReleaseMutex(hMutex);  }  return 0;  
}  


执行结果 :

代码实例 2.2 无Mutex​​​​​​​

#include "StdAfx.h"  
#include <iostream>  
#include <windows.h>  using namespace std;  DWORD WINAPI thread1fun(LPVOID);  
DWORD WINAPI thread2fun(LPVOID);  int tickets=20;  
HANDLE hMutex;  int main()  
{  HANDLE hthread1,hthread2;  //hMutex=CreateMutex(NULL,FALSE,_T("tickets"));  ///TRUE :main thread got mutex object  hthread1=CreateThread(NULL,0,thread1fun,NULL,0,NULL);  hthread2=CreateThread(NULL,0,thread2fun,NULL,0,NULL);  CloseHandle(hthread1);  CloseHandle(hthread2);  //if(hMutex)  {  if(ERROR_ALREADY_EXISTS==GetLastError())  {  cout<<"only instance can run!"<<endl;  return 0;  }  }  Sleep(10000);  return 0;  
}  DWORD WINAPI thread1fun(LPVOID lpParameter)  
{  while(1)  {  //WaitForSingleObject(hMutex,INFINITE);  if(tickets>0)  {  Sleep(30);  cout<<"thread 1: "<<tickets--<<endl;  }  else  break;  //ReleaseMutex(hMutex);  //释放当前线程ID,互斥对象计数器-1  }  //谁拥有互斥对象,你可以释放  return 0;  
}  DWORD WINAPI thread2fun(LPVOID lpParameter)  
{  while(1)  {  //WaitForSingleObject(hMutex,INFINITE);  if(tickets>0)  {  Sleep(10);  cout<<"thread 2: "<<tickets--<<endl;  }  else  break;  //ReleaseMutex(hMutex);  }  return 0;  
}  

 

 

 

关键代码段3.1:

#include "StdAfx.h"  
#include <iostream>  
#include <windows.h>  using namespace std;  DWORD WINAPI thread1fun(LPVOID);  
DWORD WINAPI thread2fun(LPVOID);  int tickets=20;  
CRITICAL_SECTION g_cs;  /*---    每个线程中访问临界资源的那段程序称为临界区(Critical Section) (临界资源是一次仅允许一个线程使用的共享资源)。 每次只准许一个线程进入临界区,进入后不允许其他线程进入。 不论是硬件临界资源,还是软件临界资源,多个线程必须互斥地对它进行访问. ------------------**/  
int main()  
{  HANDLE hthread1,hthread2;  InitializeCriticalSection(&g_cs);  hthread1=CreateThread(NULL,0,thread1fun,NULL,0,NULL);  //  Sleep(11);  hthread2=CreateThread(NULL,0,thread2fun,NULL,0,NULL);  CloseHandle(hthread1);  CloseHandle(hthread2);  //  while(1)  Sleep(4000);  DeleteCriticalSection(&g_cs);  return 0;  
}  DWORD WINAPI thread1fun(LPVOID lpParameter)  
{  while(1)  {     EnterCriticalSection(&g_cs);  //进入关键代码段  if(tickets>0)  {  Sleep(10);  cout<<"thread 1: "<<tickets--<<endl;  }  else  break;  LeaveCriticalSection(&g_cs);//释放临界区对象所有权  Sleep(5);  }  return 0;  
}  DWORD WINAPI thread2fun(LPVOID lpParameter)  
{  while(1)  {  EnterCriticalSection(&g_cs); /请求到信号,系统重置为无信号状态  if(tickets>0)  {  Sleep(10);  cout<<"thread 2: "<<tickets--<<endl;  }  else  break;  LeaveCriticalSection(&g_cs);  Sleep(15);  }  return 0;  
}  


执行结果 :

 

代码实例:无代码段约束3.2

#include "StdAfx.h"  
#include <iostream>  
#include <windows.h>  using namespace std;  DWORD WINAPI thread1fun(LPVOID);  
DWORD WINAPI thread2fun(LPVOID);  int tickets=20;  
CRITICAL_SECTION g_cs;  /*---    每个线程中访问临界资源的那段程序称为临界区(Critical Section) (临界资源是一次仅允许一个线程使用的共享资源)。 每次只准许一个线程进入临界区,进入后不允许其他线程进入。 不论是硬件临界资源,还是软件临界资源,多个线程必须互斥地对它进行访问. ------------------**/  
int main()  
{  HANDLE hthread1,hthread2;  //InitializeCriticalSection(&g_cs);  hthread1=CreateThread(NULL,0,thread1fun,NULL,0,NULL);  //  Sleep(11);  hthread2=CreateThread(NULL,0,thread2fun,NULL,0,NULL);  CloseHandle(hthread1);  CloseHandle(hthread2);  //  while(1)  Sleep(4000);  //DeleteCriticalSection(&g_cs);  return 0;  
}  DWORD WINAPI thread1fun(LPVOID lpParameter)  
{  while(1)  {     //EnterCriticalSection(&g_cs);  //进入关键代码段  if(tickets>0)  {  Sleep(10);  cout<<"thread 1: "<<tickets--<<endl;  }  else  break;  //LeaveCriticalSection(&g_cs);//释放临界区对象所有权  Sleep(5);  }  return 0;  
}  DWORD WINAPI thread2fun(LPVOID lpParameter)  
{  while(1)  {  //EnterCriticalSection(&g_cs); /请求到信号,系统重置为无信号状态  if(tickets>0)  {  Sleep(10);  cout<<"thread 2: "<<tickets--<<endl;  }  else  break;  //LeaveCriticalSection(&g_cs);  Sleep(15);  }  return 0;  
}  

 

转载于https://blog.csdn.net/makenothing/article/details/43269151

http://www.lryc.cn/news/2416464.html

相关文章:

  • 量子通信和传统通信的对比分析
  • keil报错:Loading PDSC Debug Description failed for STMicroelectronics STM32Fxxxxxxx
  • php ismethod,PHP的method_exists,function_exists,is_callable的区别
  • linux ioctl 函数
  • #SATA# SATA 专业术语
  • 工作流引擎 介绍
  • 权限持久化---映像劫持检测(Shift后门)
  • 【金士顿PS2251-03(PS2303)量产教程_2024】
  • Winedit修改快捷键
  • 推荐一款强大的Go语言工具:goid
  • GitHub Pages + Jekyll 快速搭建个人博客网站
  • JavaScript(BOM)中Window对象的prompt()方法
  • 注意力机制总结
  • windows配置防火墙
  • Sōsh:让宅男宅女从虚拟回到现实的社交网站
  • 一秒教你保存浏览器当前页面的所有图片
  • 若要使他人能够在远程计算机上查看此特定错误消息的详细信息,请在位于当前 Web 应用程序根目录下的“web.config”配置文件中创建一个 customErrors 标记。然后应将此 cust
  • 开放数据源
  • cetnos下gotop安装和使用
  • OpenCV AI Kit(OAK)官方答疑录
  • 数字世界的守护者——数字签名与证书全面解析!
  • java resultset getmetadata_Java ResultSetMetaData getColumnType()方法与示例
  • 网络编程2之sockaddr与sockaddr_in的区别
  • 软件体系结构风格介绍
  • Frostmourne - Elasticsearch源日志告警配置,大数据开发基础面试题
  • radmin 3.4 绿色版
  • PHP中json_decode函数
  • 一.常见的视频格式有哪些?
  • FPGA组合逻辑设计——译码器
  • EastFax电子传真信创国产化出炉,网络传真换新颜