zoukankan      html  css  js  c++  java
  • window下线程同步之(Critical Sections(关键代码段、关键区域、临界区域)----转载

    转载:https://www.cnblogs.com/cyblogs/p/9948379.html

     

     关键区域(CriticalSection)

    临界区是为了确保同一个代码片段在同一时间只能被一个线程访问,与原子锁不同的是临界区是多条指令的锁定,而原子锁仅仅对单条操作指令有效;临界区和原子锁只能控制同一个进程中线程的同步

    使用方法:

    1、初始化:InitializeCriticalSection; 
    2、删除:DeleteCriticalSection; 
    3、进入:EnterCriticalSection(可能造成阻塞); 
    4、尝试进入:TryEnterCriticalSection(不会造成阻塞); 
    5、离开:LeaveCriticalSection;

    固有特点(优点+缺点): 
    1、是一个用户模式的对象,不是系统核心对象; 
    2、因为不是核心对象,所以执行速度快,有效率; 
    3、因为不是核心对象,所以不能跨进程使用; 
    4、可以多次“进入”,但必须多次“退出”; 
    5、最好不要同时进入或等待多个 Critical Sections,容易造成死锁; 
    6、无法检测到进入到 Critical Sections 里面的线程当前是否已经退出!

    一般错误的情况:

    复制代码
    #include <stdio.h> 
    #include <windows.h>
    
    long g_nNum = 0 ; 
    DWORD WINAPI ThreadProc(__in  LPVOID lpParameter); 
    const int THREAD_NUM = 10;
    
    int main() 
    {
    
        HANDLE  handle[THREAD_NUM];    
        g_nNum = 0; 
        int var = 0; 
        while ( var< THREAD_NUM) 
        { 
            handle[ var++] = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
    
        } 
        WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
    
        for( var=0; var<sizeof(handle); var++) 
        { 
            CloseHandle(handle[var]); 
        }
    
        return 0; 
    }
    
    DWORD WINAPI ThreadProc(__in  LPVOID lpParameter) 
    { 
        Sleep(50); 
        g_nNum++; 
        Sleep(0); 
        printf("当前计数为:%d
    ",g_nNum); 
        return 0; 
    }
    复制代码

    运行2次结果:

    image

    image

    用了关键区域的情况:

    复制代码
    #include <stdio.h> 
    #include <windows.h>
    
    long g_nNum = 0 ; 
    DWORD WINAPI ThreadProc(__in  LPVOID lpParameter); 
    const int THREAD_NUM = 10;
    
    CRITICAL_SECTION g_ThreadCode;
    
    int main() 
    {
    
        HANDLE  handle[THREAD_NUM];    
        g_nNum = 0; 
        int var = 0; 
        InitializeCriticalSection(&g_ThreadCode); 
        while ( var< THREAD_NUM) 
        { 
            handle[ var++] = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); 
        } 
        WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); 
        DeleteCriticalSection( &g_ThreadCode ); 
        
        for( var=0; var<sizeof(handle); var++) 
        { 
            CloseHandle(handle[var]); 
        }
    
        return 0; 
    }
    
    DWORD WINAPI ThreadProc(__in  LPVOID lpParameter) 
    {  
        EnterCriticalSection( &g_ThreadCode ); 
        g_nNum++;  
        printf("当前计数为:%d
    ",g_nNum); 
        LeaveCriticalSection( &g_ThreadCode ); 
        return 0; 
    }
    复制代码
  • 相关阅读:
    ffmpeg和opencv 播放视频文件和显示器
    ExtJS学习笔记:定义extjs类别
    debian软件安装基础(同tomcat案件)
    java逼出来的递归中间
    HDOJ 1047 Integer Inquiry
    BZOJ 3589 动态树 树链拆分+纳入和排除定理
    hdu 4884 TIANKENG’s rice shop(模拟)
    JQuery EasyUI学习框架
    excel
    Java和C#中String直接赋值与使用new创建(==与equals进行比较)的区别
  • 原文地址:https://www.cnblogs.com/cyblogs/p/9948471.html
Copyright © 2011-2022 走看看