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中间的代码执行过程不会被其他线程干拢或者这么讲不允许其他线程中
    的代码执行。这样可以有效防止一个全局变量在两个线程中同时被操作的可能性

  • 相关阅读:
    【WPF】 Prism 框架中,TabControl 作为Region时如何设置Header
    【WPF】将控件事件中的参数,传递到ViewModel中
    WPF 一种带有多个子集的类ComBox 解决方法
    WPF TabControl美化
    【WPF】 问题总结-RaidButton修改样式模板后作用区域的变化
    C# 打开Excel文件
    获取文件夹下所有的文件名
    访问需要HTTP Basic Authentication认证的资源的c#的实现 将账号密码放入url
    第十三章 建造者模式(Builder)
    第十二章 外观模式 (Facade)
  • 原文地址:https://www.cnblogs.com/sevenyuan/p/1911670.html
Copyright © 2011-2022 走看看