July7th

导航

C++多线程3

#include "stdafx.h"
#include <windows.h>
#include <process.h>  

int g_count;
const int ThreadNum = 10;
unsigned int __stdcall Func(LPVOID pm)
{
    int id = *(int*)pm;
    Sleep(10);
    g_count++;
    printf_s("id=%d,count=%d \n", id, g_count);
    return 0;
}

int main()
{
    HANDLE  handle[ThreadNum];
    g_count = 0;
    for (int i = 0; i < ThreadNum; ++i)
    {
        handle[i] = (HANDLE)_beginthreadex(NULL, 0, Func, (LPVOID)&i, 0, NULL);
    }
    WaitForMultipleObjects(ThreadNum, handle, TRUE, INFINITE);
    system("pause");
    return 0;
}

要求:

子线程输出的线程序号不能重复。(主线程和子线程需要同步)

全局变量g_count的输出必须递增。(子线程之间需要互斥)

 

1,用临界区CRITICAL_SECTION来解决子线程之间的互斥

CRITICAL_SECTION g_section;//声明一个临界区资源
InitializeCriticalSection(&g_section);//初始化
EnterCriticalSection(&g_section);//开始进入临界区代码段
LeaveCriticalSection(&g_section);//离开临界区代码段
DeleteCriticalSection(&g_section);//销毁
#include "stdafx.h"
#include <windows.h>
#include <process.h>  

int g_count;
const int ThreadNum = 10;
CRITICAL_SECTION g_section;
unsigned int __stdcall Func(LPVOID pm)
{
    int id = *(int*)pm;
    Sleep(10);
    EnterCriticalSection(&g_section);//进入临界区后各个线程之间互斥
    g_count++;
    //InterlockedIncrement((LPLONG)&g_count);
    printf_s("id=%d,count=%d \n", id, g_count);
    LeaveCriticalSection(&g_section);
    return 0;
}

int main()
{
    InitializeCriticalSection(&g_section);
    HANDLE  handle[ThreadNum];
    g_count = 0;
    for (int i = 0; i < ThreadNum; ++i)
    {
        handle[i] = (HANDLE)_beginthreadex(NULL, 0, Func, (LPVOID)&i, 0, NULL);
    }
    WaitForMultipleObjects(ThreadNum, handle, TRUE, INFINITE);
    DeleteCriticalSection(&g_section);
    system("pause");
    return 0;
}

 

2用事件解决主线程和子线程的同步问题

//CreateEvent创建一个事件

HANDLE CreateEvent(

 LPSECURITY_ATTRIBUTES lpEventAttributes,//安全参数,一般为NULL

 BOOL bManualReset, //TRUE手动(SetEvent后需要ResetEvent) , FALSE自动,对事件对象调用WaitForSingleObject后自动是对象变成未触发的状态

 BOOL bInitialState, //TRUE 初始状态就是触发状态

 LPCTSTR lpName //事件对象的名字,传入NULL表示匿名的事件对象

);

//SetEvent 触发一个事件内核对象,必有一个或者多个等待状态的线程变成可调度的状态

BOOL SetEvent(HANDLE hEvent);

//ResetEvent 事件变成未触发状态

BOOL ResetEvent (HANDLE hEvent);

最后的代码如下

#include "stdafx.h"
#include <windows.h>
#include <process.h>  

int g_count;
const int ThreadNum = 10;
CRITICAL_SECTION g_section;
HANDLE g_handle;

unsigned int __stdcall Func(LPVOID pm)
{
    int id = *(int*)pm;
    SetEvent(g_handle);//事件被触发后,线程变成可调度状态
    Sleep(10);
    EnterCriticalSection(&g_section);//进入临界区
    g_count++;
    printf_s("id=%d,count=%d \n", id, g_count);//离开临界区
    LeaveCriticalSection(&g_section);
    return 0;
}

int main()
{
    g_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
    InitializeCriticalSection(&g_section);

    HANDLE  handle[ThreadNum];
    g_count = 0;
    for (int i = 0; i < ThreadNum; ++i)
    {
        handle[i] = (HANDLE)_beginthreadex(NULL, 0, Func, &i, 0, NULL);
        WaitForSingleObject(g_handle, INFINITE);//等待事件被触发
    }
    WaitForMultipleObjects(ThreadNum, handle, TRUE, INFINITE);//等待所有的子线程被触发
    CloseHandle(g_handle);
    DeleteCriticalSection(&g_section);
    system("pause");
    return 0;
}

输出

id没有相同的,说明主线程和子线程之间已经同步,

count递增,说明子线程之间已经互斥

 

posted on 2017-01-01 22:25  July7th  阅读(158)  评论(0编辑  收藏  举报