多线程编程

1.问题的提出

希望实现如下功能:一个加法线程实现对全局变量a执行加法操作,另一个减法线程对全局变量a执行减法操作,当a大于30时,退出加法线程,当a小于等于0时,退出减法线程。

2.代码的实现

// CThreadPoolTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#define _AFXDLL
#include <afxwin.h>

//全局操作变量
int a = 10;
//加法线程
CWinThread *addThread = NULL;
//减法线程
CWinThread *minusThread = NULL;
//临界区资源对象
CRITICAL_SECTION cs;

UINT add(LPVOID lParameters)
{
    while (true) {
        EnterCriticalSection(&cs);
        printf("add thread. a = %d\n", a);
        a += 2;
        if (a >= 30) {
            printf("退出线程add \n");
            LeaveCriticalSection(&cs);   //1
            //break;
            DWORD dwExitCode = 0;
            GetExitCodeThread(addThread->m_hThread, &dwExitCode);
            AfxEndThread(dwExitCode, TRUE);     
        }
        LeaveCriticalSection(&cs);
    }

    return 0;
}

UINT minus(LPVOID lParameters)
{
    while (true) {
        EnterCriticalSection(&cs);
        printf("minus thread. a = %d\n", a);
        a -= 1;
        if (a <= 0) {
            printf("退出线程minus. a = %d\n",a);
            LeaveCriticalSection(&cs);     //1
            //break;
            DWORD dwExitCode = 0;
            GetExitCodeThread(minusThread->m_hThread, &dwExitCode);
            AfxEndThread(dwExitCode, TRUE);         
        }
        LeaveCriticalSection(&cs);
    }

    return 0;
}

int main()
{
    //初始化临界区资源对象
    InitializeCriticalSection(&cs);
    //创建CWinThread线程
    addThread = AfxBeginThread(add,LPVOID(NULL), THREAD_PRIORITY_NORMAL,0,NULL);
    minusThread = AfxBeginThread(minus, LPVOID(NULL), THREAD_PRIORITY_NORMAL, 0, NULL);

    _gettch();

    return 0;
}

3.多线程编程函数

a)线程创建
AfxBeginThread
定义有两种形式:

CWinThread* AfxBeginThread( 
   AFX_THREADPROC pfnThreadProc, 
   LPVOID pParam, 
   int nPriority = THREAD_PRIORITY_NORMAL, 
   UINT nStackSize = 0, 
   DWORD dwCreateFlags = 0, 
   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL  
); 
CWinThread* AfxBeginThread( 
   CRuntimeClass* pThreadClass, 
   int nPriority = THREAD_PRIORITY_NORMAL, 
   UINT nStackSize = 0, 
   DWORD dwCreateFlags = 0, 
   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL  
);

第一个形式是工作者线程,其参数定义如下:

pfnThreadProc线程的函数入口,此函数的声明形式一定要是 UINT ThreadFunctioon(LPVOID pParam),不能设置为NULL
pParam传递到线程函数的参数
nPriority线程的优先级。设置为0,表示和主线程拥有相同的优先级
nStackSize指定新创建的线程的栈的大小.如果为 0。新创建的线程具有和主线程一样的大小的栈
dwCreateFlags指定创建线程以后,线程的标志.可以指定两个值:CREATE_SUSPENDED : 线程创建以后,会处于挂起状态,直到调用:ResumeThread;0 : 创建线程后就开始运行.
lpSecurityAttrs指向一个 SECURITY_ATTRIBUTES 的结构体,用它来标志新创建线程的安全性.如果为 NULL,那么新创建的线程就具有和主线程一样的安全性.

第二个形式是用户界面线程

pThreadClass从CWinThread派生的RUNTIME_CLASS类
nPriority线程的优先级。设置为0,表示和主线程拥有相同的优先级
nStackSize指定新创建的线程的栈的大小.如果为 0。新创建的线程具有和主线程一样的大小的栈
dwCreateFlags指定创建线程以后,线程的标志.可以指定两个值:CREATE_SUSPENDED : 线程创建以后,会处于挂起状态,直到调用:ResumeThread;0 : 创建线程后就开始运行.
lpSecurityAttrs指向一个 SECURITY_ATTRIBUTES 的结构体,用它来标志新创建线程的安全性.如果为 NULL,那么新创建的线程就具有和主线程一样的安全性.

b)线程的退出
一种使用AfxEndThread方式

void AFXAPI AfxEndThread( 
   UINT nExitCode, 
   BOOL bDelete = TRUE  
);
nExitCode线程的退出码
bDelete是否从内存删除线程对象

GetExitCodeThread

BOOL WINAPI GetExitCodeThread(
  _In_  HANDLE  hThread,
  _Out_ LPDWORD lpExitCode
);
hThread线程句柄
lpExitCode保存线程退出状态的变量

第二种使用当满足一定条件退出死循环的方式,如下:

//add函数
            printf("退出线程add \n");
            LeaveCriticalSection(&cs);
            break;
            //DWORD dwExitCode = 0;
            //GetExitCodeThread(addThread->m_hThread, &dwExitCode);
            //AfxEndThread(dwExitCode, TRUE);   
//minus函数
            printf("退出线程minus. a = %d\n",a);
            LeaveCriticalSection(&cs);
            break;
            //DWORD dwExitCode = 0;
            //GetExitCodeThread(minusThread->m_hThread, &dwExitCode);
            //AfxEndThread(dwExitCode, TRUE);   

4.注意

对于使用临界区控制全局变量的时候,要特别注意避免死锁问题的出现。
比如还是上面的那个程序,当把两个线程函数中的if语句块内的

LeaveCriticalSection(&cs); 

屏蔽掉后运行,会发现,当退出add或者minus之后,另一个线程无法执行到输出退出信息,就是由于当其他一个线程退出时,未能释放锁导致的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

祝云飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值