zoukankan      html  css  js  c++  java
  • 线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的用法

    转自:http://www.itcodeworld.com/?p=105

    使用结构CRITICAL_SECTION 需加入头文件#include “afxmt.h”

    定义一个全局的锁 CRITICAL_SECTION的实例
    和一个静态全局变量

    CRITICAL_SECTION cs;//可以理解为锁定一个资源
    static int n_AddValue = 0;//定义一个静态的全部变量n_AddValue

    创建两个线程函数,代码实现如下:

    代码
    //第一个线程
    UINT FirstThread(LPVOID lParam)
    {
    EnterCriticalSection(
    &cs);//加锁 接下来的代码处理过程中不允许其他线程进行操作,除非遇到LeaveCriticalSection
    for(int i = 0; i<10; i++){
    n_AddValue
    ++;
    cout
    << "n_AddValue in FirstThread is "<<n_AddValue <<endl;
    }
    LeaveCriticalSection(
    &cs);//解锁 到EnterCriticalSection之间代码资源已经释放了,其他线程可以进行操作
    return 0;
    }
    //第二个线程
    UINT SecondThread(LPVOID lParam)
    {
    EnterCriticalSection(
    &cs);//加锁
    for(int i = 0; i<10; i++){
    n_AddValue
    ++;
    cout
    << "n_AddValue in SecondThread is "<<n_AddValue <<endl;

    }
    LeaveCriticalSection(
    &cs);//解锁
    return 0;
    }

    在主函数添加以下代码

    代码
    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
    int nRetCode = 0;

    // 初始化 MFC 并在失败时显示错误
    if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
    {
    // TODO: 更改错误代码以符合您的需要
    _tprintf(_T("错误: MFC 初始化失败\n"));
    nRetCode
    = 1;
    }
    else
    {
    InitializeCriticalSection(
    &cs);//初始化结构CRITICAL_SECTION

    CWinThread
    *pFirstThread,*pSecondThread;//存储函数AfxBeginThread返回的CWinThread指针

    pFirstThread
    = AfxBeginThread(FirstThread,LPVOID(NULL));//启动第一个线程
    pSecondThread = AfxBeginThread(SecondThread,LPVOID(NULL));//启动第二个线程

    HANDLE hThreadHandle[
    2];//
    hThreadHandle[0] = pFirstThread->m_hThread;
    hThreadHandle[
    1] = pSecondThread->m_hThread;

    //等待线程返回
    WaitForMultipleObjects(2,hThreadHandle,TRUE,INFINITE);
    }

    return nRetCode;
    }

    输出:

    n_AddValue in FirstThread is 1
    n_AddValue in FirstThread is 2
    n_AddValue in FirstThread is 3
    n_AddValue in FirstThread is 4
    n_AddValue in FirstThread is 5
    n_AddValue in FirstThread is 6
    n_AddValue in FirstThread is 7
    n_AddValue in FirstThread is 8
    n_AddValue in FirstThread is 9
    n_AddValue in FirstThread is 10
    n_AddValue in SecondThread is 11
    n_AddValue in SecondThread is 12
    n_AddValue in SecondThread is 13
    n_AddValue in SecondThread is 14
    n_AddValue in SecondThread is 15
    n_AddValue in SecondThread is 16
    n_AddValue in SecondThread is 17
    n_AddValue in SecondThread is 18
    n_AddValue in SecondThread is 19
    n_AddValue in SecondThread is 20

    如果把两个线程函数中的EnterCriticalSection和LeaveCriticalSection位置移到for循环中去,线程的执行顺序将会改变
    输出也就跟着改变,如:

    代码
    //第一个线程
    UINT FirstThread(LPVOID lParam)
    {

    for(int i = 0; i<10; i++){
    EnterCriticalSection(
    &cs);//加锁 锁移到for循环内部里
    n_AddValue ++;
    cout
    << "n_AddValue in FirstThread is "<<n_AddValue <<endl;
    LeaveCriticalSection(
    &cs);//解锁
    }
    return 0;
    }

    //第二个线程
    UINT SecondThread(LPVOID lParam)
    {

    for(int i = 0; i<10; i++){
    EnterCriticalSection(
    &cs);//加锁
    n_AddValue ++;
    cout
    << "n_AddValue in SecondThread is "<<n_AddValue <<endl;
    LeaveCriticalSection(
    &cs);//解锁
    }
    return 0;
    }

    其他代码不变,输出的结果如下:

    n_AddValue in FirstThread is 1
    n_AddValue in SecondThread is 2
    n_AddValue in FirstThread is 3
    n_AddValue in SecondThread is 4
    n_AddValue in FirstThread is 5
    n_AddValue in SecondThread is 6
    n_AddValue in FirstThread is 7
    n_AddValue in SecondThread is 8
    n_AddValue in FirstThread is 9
    n_AddValue in SecondThread is 10
    n_AddValue in FirstThread is 11
    n_AddValue in SecondThread is 12
    n_AddValue in FirstThread is 13
    n_AddValue in SecondThread is 14
    n_AddValue in FirstThread is 15
    n_AddValue in SecondThread is 16
    n_AddValue in FirstThread is 17
    n_AddValue in SecondThread is 18
    n_AddValue in FirstThread is 19
    n_AddValue in SecondThread is 20

    个人认为在函数EnterCriticalSection和LeaveCriticalSection中间的代码执行过程不会被其他线程干拢或者这么讲不允许其他线程中
    的代码执行。这样可以有效防止一个全局变量在两个线程中同时被操作的可能性

  • 相关阅读:
    linux系统,CentOs7加新硬盘
    mysql学习笔记11_12(查询)
    No manual entry for printf in section 3
    MyBatis-Plus的条件构造器 EntryWrapper和Condition
    MyBatis-Plus 通用CRUD启动注入SQL原理分析
    Spring框架中Bean的生命周期
    Spring bean的作用域
    成员变量和局部变量
    类初始化和实例初始化
    JVM详解
  • 原文地址:https://www.cnblogs.com/sevenyuan/p/1911670.html
Copyright © 2011-2022 走看看