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