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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值