zoukankan      html  css  js  c++  java
  • 互斥体

    DWORD WaitForSingleObject(
    HANDLE hHandle, // handle to object
    DWORD dwMilliseconds // time-out interval
    );

    功能说明:

    等待函数可使线程自愿进入等待状态,直到一个特定的内核对象变为已通知状态为止.

    hHandle:

    内核对象句柄,可以是进程也可以是线程.

    dwMilliseconds:

    等待时间,单位是毫秒 INFINITE(-1)一直等待

    返回值:

    WAIT_OBJECT_0(0) 等待对象变为已通知

    WAIT_TIMEOUT(0x102) 超时


    特别说明:

    1、内核对象中的每种对象都可以说是处于已通知或未通知的状态之中

    2、这种状态的切换是由Microsoft为每个对象建立的一套规则来决定的

    3、当线程正在运行的时候,线程内核对象处于未通知状态

    4、当线程终止运行的时候,它就变为已通知状态

    5、在内核中就是个BOOL值,运行时FALSE 结束TRUE

    代码演示:

    DWORD WINAPI ThreadProc1(LPVOID lpParameter)
    {
    for(int i=0;i<5;i++)
    {
    printf("+++++++++ ");
    Sleep(1000);
    }
    return 0;
    }

    int main(int argc, char* argv[])
    {

    //创建一个新的线程
    HANDLE hThread1 = ::CreateThread(NULL, 0, ThreadProc1,
    NULL, 0, NULL);

    DWORD dwCode = ::WaitForSingleObject(hThread1, INFINITE);

    MessageBox(0,0,0,0);

    return 0;
    }


    DWORD WaitForMultipleObjects(
    DWORD nCount, // number of handles in array
    CONST HANDLE *lpHandles, // object-handle array
    BOOL bWaitAll, // wait option
    DWORD dwMilliseconds // time-out interval
    );

    功能说明:

    同时查看若干个内核对象的已通知状态

    nCount:

    要查看内核对象的数量

    lpHandles:

    内核对象数组

    bWaitAll:

    等到类型 TRUE 等到所有变为已通知 FALSE 只要有一个变为已通知

    dwMilliseconds:

    超时时间

    INFINITE一直等待

    返回值:

    bWaitAll为TRUE时,返回WAIT_OBJECT_0(0) 代码所以内核对象都变成已通知

    bWaitAll为FALSE时,返回最先变成已通知的内核对象在数组中的索引

    WAIT_TIMEOUT(0x102) 超时


    代码演示:

    DWORD WINAPI ThreadProc1(LPVOID lpParameter)
    {
    for(int i=0;i<5;i++)
    {
    printf("+++++++++ ");
    Sleep(1000);
    }
    return 0;
    }

    DWORD WINAPI ThreadProc2(LPVOID lpParameter)
    {
    for(int i=0;i<3;i++)
    {
    printf("--------- ");
    Sleep(1000);
    }

    return 0;
    }


    int main(int argc, char* argv[])
    {

    HANDLE hArray[2];

    //创建一个新的线程
    HANDLE hThread1 = ::CreateThread(NULL, 0, ThreadProc1,
    NULL, 0, NULL);

    //创建一个新的线程
    HANDLE hThread2 = ::CreateThread(NULL, 0, ThreadProc2,
    NULL, 0, NULL);

    hArray[0] = hThread1;
    hArray[1] = hThread2;

    DWORD dwCode = ::WaitForMultipleObjects(2, hArray,FALSE,INFINITE);

    MessageBox(0,0,0,0);

    return 0;
    }



    进程一:

    HANDLE g_hMutex = CreateMutex(NULL,FALSE, "XYZ");


    进程二:

    HANDLE g_hMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE, "XYZ");

    WaitForSingleObject(g_hMutex,INFINITE);

    //逻辑代码

    ReleaseMutex(g_hMutex);


    进程三:

    HANDLE g_hMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE, "XYZ");

    WaitForSingleObject(g_hMutex,INFINITE);

    //逻辑代码

    ReleaseMutex(g_hMutex);





    互斥体与临界区的区别:

    1、临界区只能用于单个进程间的线程控制.

    2、互斥体可以设定等待超时,但临界区不能.

    3、线程意外终结时,Mutex可以避免无限等待.

    4、Mutex效率没有临界区高.

    以下是抢红包程序:

    // hongbao.cpp : Defines the entry point for the application.
    //
    
    #include "stdafx.h"
    #include "resource.h"
    #include<stdio.h>
    
    HWND hEdit1;
    HWND hEdit2;
    HWND hEdit3;
    HWND hEdit4;
    HANDLE hMutex;
    int num = 1000;
    
    DWORD WINAPI ProcThread1(LPVOID lpParameter)
    {
        TCHAR szBuff[10] = {0};
        int flag =  0;
        HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "XYZ");
        while(num >= 50)
        {
            WaitForSingleObject(hMutex, INFINITE);
        //    GetWindowText(hEdit1, szBuff, 10);
        //    sscanf(szBuff, "%d", &flag);
            num -= 50;
            flag += 50;    
            sprintf(szBuff, "%d", num);
            SetWindowText(hEdit1, szBuff);
            memset(szBuff, 0, 10);
            sprintf(szBuff, "%d", flag);
            SetWindowText(hEdit2, szBuff);
            ExitThread(2);
            ReleaseMutex(hMutex);
            Sleep(1000);
        }
    
        return 0;
    }
    
    DWORD WINAPI ProcThread2(LPVOID lpParameter)
    {
        TCHAR szBuff[10] = {0};
        int flag =  0;
        HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "XYZ");
        while(num >= 50)
        {
            WaitForSingleObject(hMutex, INFINITE);
        //    GetWindowText(hEdit1, szBuff, 10);
        //    sscanf(szBuff, "%d", &flag);
            num -= 50;
            flag += 50;    
            sprintf(szBuff, "%d", num);
            SetWindowText(hEdit1, szBuff);
            memset(szBuff, 0, 10);
            sprintf(szBuff, "%d", flag);
            SetWindowText(hEdit3, szBuff);
            ReleaseMutex(hMutex);
            Sleep(2000);
        }
    
        return 0;
    }
    
    DWORD WINAPI ProcThread3(LPVOID lpParameter)
    {
        TCHAR szBuff[10] = {0};
        int flag =  0;
        HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "XYZ");
        while(num >= 50)
        {
            WaitForSingleObject(hMutex, INFINITE);
        //    GetWindowText(hEdit1, szBuff, 10);
        //    sscanf(szBuff, "%d", &flag);
            num -= 50;
            flag += 50;    
            sprintf(szBuff, "%d", num);
            SetWindowText(hEdit1, szBuff);
            memset(szBuff, 0, 10);
            sprintf(szBuff, "%d", flag);
            SetWindowText(hEdit4, szBuff);
            ReleaseMutex(hMutex);
            Sleep(3000);
        }
        return 0;
    
    }
    
    
    DWORD WINAPI  ProcThread(LPVOID lpParameter)
    {
        hMutex = CreateMutex(NULL, FALSE, "XYZ");
        HANDLE hHandleArr[3];
    
        hHandleArr[0] = ::CreateThread(NULL, 0, ProcThread1, NULL, 0, NULL);
        hHandleArr[1] = ::CreateThread(NULL, 0, ProcThread2, NULL, 0, NULL);
        hHandleArr[2] = ::CreateThread(NULL, 0, ProcThread3, NULL, 0, NULL);
        
        ::WaitForMultipleObjects(3, hHandleArr, TRUE, INFINITE);
        ::CloseHandle(hMutex);
        return 0;
    }
    
    BOOL CALLBACK ProcDialog(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch(uMsg)
        {
        case WM_INITDIALOG:
            hEdit1 = GetDlgItem(hwnd, IDC_EDIT1);
            SetWindowText(hEdit1, "1000");
            hEdit2 = GetDlgItem(hwnd, IDC_EDIT2);
            SetWindowText(hEdit2, "0");
            hEdit3 = GetDlgItem(hwnd, IDC_EDIT3);
            SetWindowText(hEdit3, "0");
            hEdit4 = GetDlgItem(hwnd, IDC_EDIT4);
            SetWindowText(hEdit4, "0");
            break;
        case WM_CLOSE:
            EndDialog(hwnd, 0);
            break;
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
            case IDC_BUTTON1:
                HANDLE hThread = ::CreateThread(NULL, 0, ProcThread, NULL, 0, NULL);
                ::CloseHandle(hThread);
                return TRUE;
            }
            break;
        }
        return FALSE;
    
    }
    
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
    {
         // TODO: Place code here.
        DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, ProcDialog);
        return 0;
    }
  • 相关阅读:
    分部视图在ASP.NET MVC中的应用
    SVN、Git设置提交时忽略的文件
    TortoiseSVN使用步骤和trunk,Branch,Tag详细说明
    SQL Server系统表介绍与使用
    C#中Task的使用简单总结
    Auto Encoder用于异常检测
    mac bash 下使用vi 快捷方式——因为没有alt键 所以没有办法 用vi模式也非常方便的
    daal utils printNumericTable
    https 不会被中间人攻击——因为中间人即使拿到了数据,也是加密的
    Let's Encrypt 免费通配符 SSL 证书申请教程——但是也需要email,域名所有权等,如果是黑产用的话会这样用吗?会不会暴露自己身份???
  • 原文地址:https://www.cnblogs.com/Lu3ky-Athena/p/13720912.html
Copyright © 2011-2022 走看看