码迷,mamicode.com
首页 > 编程语言 > 详细

多线程编程示例(结合实例)

时间:2015-08-09 22:25:56      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:

1.CreateThread与_beginthreadex

#pragma once

#include<cstdio>
#include<Windows.h>
#include<crtdbg.h>
#include<process.h>

//子线程函数
DWORD WINAPI ThreadFun1(LPVOID pM)
{
    printf("子线程的线程ID号为:%d\nHello world!\n",GetCurrentThreadId());
    return 0;
}

void fun1()
{
    printf("简单多线程实例!\n\n");

    /*
       CreateThread参数解析
       1:线程内核安全属性
       2:线程栈空间大小
       3:线程执行函数地址
       4:传给线程执行函数参数
       5:线程创建控制参数(CREATE_SUSPENDED)
       6:线程ID号
    */
    HANDLE handle = CreateThread(NULL, 0, ThreadFun1, NULL, 0, NULL);
    WaitForSingleObject(handle, INFINITE);
    CloseHandle(handle);
}

//设置计数全局变量
int COUNT = 0;

//子线程函数
unsigned int _stdcall ThreadFun2(PVOID pM)
{
    ++COUNT;
    printf("子线程的线程ID号为:%d,报数为%d\nHello world!\n", GetCurrentThreadId(),COUNT);
    return 0;
}

void fun2()
{
    printf("简单多线程实例!\n\n");

    const int THREAD_NUM = 5;
    HANDLE handle[THREAD_NUM];

    for (size_t i = 0; i < THREAD_NUM; i++)
    {
        handle[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFun2, NULL, 0, NULL);
    }
    WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
}

int main(void)
{
    //使用CreateThread
    //fun1();

    //使用_beginthreadex
    //推荐使用原因为:使用标准C运行库函数时,易发生race condition
    //使用_beginthreadex可以避免数据被其他线程篡改
    //更加合理的解释可以参考Win32多线程编程
    fun2();

    //检测内存泄漏
    _CrtDumpMemoryLeaks();
    return 0;
}

其中执行fun2结果为:(蛮有趣的,不加锁竟然这么直观)

技术分享

 

2.原子操作

#pragma once

#include<cstdio>
#include<Windows.h>
#include<crtdbg.h>
#include<process.h>

volatile long COUNT = 0;
const int THREAD_NUM = 500;

unsigned int _stdcall ThreadFun(LPVOID pM)
{
    Sleep(50);
    //++COUNT;
    InterlockedIncrement((LPLONG)&COUNT); //使用原子锁替换
    Sleep(50);
    return 0;
}

void fun1()
{
    HANDLE handle[THREAD_NUM];

    for (size_t i = 0; i < THREAD_NUM; i++)
    {
        handle[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadFun, NULL, 0, NULL);
    }
    WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
    printf("有%d个线程启动,记录结果为%d", THREAD_NUM, COUNT);
}

int main()
{
    //test1
    fun1(); //易发现线程启动数和计数不匹配

    //检测内存泄漏
    _CrtDumpMemoryLeaks();
    return 0;
}

这里++操作在汇编层面是分成三层的:(1)取值由内存存至寄存器;(2)寄存器中进行操作;(3)数值由寄存器转储至内存。这个过程容易出现问题。

但是使用原子操作在只有50个线程启动时准确,但是上限调至500次时,线程启动数和计数又不一致。

技术分享

多线程编程示例(结合实例)

标签:

原文地址:http://www.cnblogs.com/jason1990/p/4716428.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!