C++:多线程类库的设计与实现(二)

来源:互联网 发布:亚伟晓军判卷软件下载 编辑:程序博客网 时间:2024/05/16 12:31
原文地址:http://yuyunwu.blog.sohu.com/63938059.html

历史回顾---C时代的多线程设计


上一篇文章中说明了我们的线程类的设计目标是简单、实用和方便移植,然后说明了我们在LinuxWindows上的开发环境。为简单起见,在后续内容中我们将使用Linux作为主要开发平台,以g++(gcc)3.4.4为开发环境。

我们首先来回顾一下在C中是怎样设计多线程程序的。

 
假设我们要设计一个程序,它包含两个线程。主线程用于响应用户命令,当用户在标准输入上键入quit并按下回车后就结束程序,另外一个线程则每隔3秒钟在标准输出上打印一行I am alive消息。

这样的程序应该是下面这个样子。

 
// File : thread1.c

 
#include <stdio.h>

#include <unistd.h>

 
extern volatile int g_iQuitFlag;

void *thread1_function(void *arg) {

    while(g_iQuitFlag != 1) {

        printf("I am alive.\n");

        sleep(3);

    }      

    return NULL;

}

//--EOF--

 

// File : main.c

 
#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <pthread.h>

 
volatile int g_iQuitFlag;

extern void *thread1_function(void *arg);

 
int main()

{

    char szBuf[1024];

    int iRes;

    pthread_t t1;

   
    
iRes = pthread_create(&t1, NULL, thread1_function, NULL);

    if (iRes != 0) {

        perror("Calling pthread_create failed.");

        exit(-1);

    }

   
    
while(1) {

        fgets(szBuf, sizeof(szBuf), stdin);

        if(0 == strncmp(szBuf, "quit", 4)) {

            g_iQuitFlag = 1;

            break;

        }

    }

   
    
pthread_join(t1, NULL);

    return 0;

}

//--EOF--

 

两个文件应该被放到同一个目录下,编译命令为:

g++ main.c thread1.c -lpthread

 

环境配置没有问题的话,编译器(以及被自动调用的链接器)将产生一个名为a.out的文件。执行该文件:

xxxx$ ./a.out

 

到目前为止,一切看起来都很顺利。我们为子线程编写一个例程函数,然后在主线程创建子线程。主线程中通过改变全局变量的值来通知子线程结束自己。主线程在设置该全局变量后等待子线程结束后退出,程序结束。

 

上面的例子中有一个小问题,就是用户在输入“quit”后程序不是立即退出的,需要等一小会。这是因为子线程每隔3秒钟检查一次退出标志,在下一个3秒钟到来之前子线程是没有响应的。我们在稍后的文章中将介绍一个更好的办法来解决这个问题。

 

这个程序的Windows版本如下。


// File : thread1.c

 
#include <Windows.h>

#include <stdio.h>

 
extern volatile int g_iQuitFlag;

 
DWORD WINAPI thread1_function(LPVOID arg) {

    while(g_iQuitFlag != 1) {

        printf("I am alive.\n");

        Sleep(3 * 1000);

    }      

    return 0;

}

//--EOF--

 

// File : main.c

 
#include <Windows.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

  
volatile int g_iQuitFlag;

extern DWORD WINAPI thread1_function(LPVOID arg);

 
int main()

{

    char szBuf[1024];

    HANDLE t1;

    t1 = CreateThread(NULL,

                     0,

                     thread1_function,

                     NULL,

                     0,

                     NULL);

   
    
if (t1 == NULL) {

        perror("Calling pthread_create failed.");

        exit(-1);

    }

   
    
while(1) {

        fgets(szBuf, sizeof(szBuf), stdin);

        if(0 == strncmp(szBuf, "quit", 4)) {

            g_iQuitFlag = 1;

            break;

        }

    }

   
    
WaitForSingleObject(t1, INFINITE);

    CloseHandle(t1);

    return 0;

}

//--EOF--

 

注意到WindowsSleep单位是毫秒,而Linuxsleep单位是秒。另外Windows的线程句柄需要在线程结束后被关闭。

 

我们可以使用IDE建立一个程序项目来编译程序,也可以使用命令行来编译。命令行的编译指令为:

cl main.c thread1.c /MT

 

注意VC++的多线程库开关MT。使用IDE的场合也需要打开多线程库支持开关。



原创粉丝点击