线程编程常见API简介(上)

来源:互联网 发布:仿链家房产源码 编辑:程序博客网 时间:2024/05/22 01:55

 

一、概述

      本文主要讲述了 Posix 标准的常用线程 API 接口的使用,目前 Linux/Unix 均提供了遵循 Posix 标准的线程编程 API,微软提供了自己的一套接口,acl  线程模块库根据 Posix 标准,提供了跨平台(支持 LINUX/WIN32)的线程库,接口定义及参数含义均与 Posix 的相同。如果您对 Linux 下的线程 API 比较熟悉,则当需要移植您的程序至 WIN32 平台时,只要需要在所用线程 API 前加前缀 acl_,同时将 acl 的 lib_acl.a 及相应头文件集成到您的程序中,即可将 LINUX 下线程程序移植至 WIN32 平台。

 

二、常用API 介绍

1)创建线程 API:pthread_create,在 acl 库中的表现形式:acl_pthread_create

/** * 创建独立的线程,使处理任务在该线程中运行,线程运行完毕,该线程的创建者 * 可以接收该线程的退出返回值 * @param tid {pthread_t*} 当线程创建成功时,该变量所指内存区域存储线程 *    的线程 ID 号 * @param attr{pthread_attr_t*} 创建线程的属性,该属性里可以设定线程的 *    堆栈大小、是否与创建线程分离等 * @param start_routine {void *(*)(void*)} 线程成功创建后开始运行的函数指针, *    该函数指针是用户应用的功能函数入口,函数的参数也由用户指定 * @param arg {void*} start 函数运行时传入的参数,该参数由用户设定 * @return {int} 线程创建是否成功,返回 0 表示成功,否则表示失败 * */int pthread_create(pthread_t* tid, pthread_attr_t* attr, void *(*start)(void*), void *arg); 

      该 API 中有两个参数类型:pthread_t 和 pthread_attr_t,其中的创建线程属性的类型 pthread_attr_t 一般由下面 API 来初始化。

2)初始化/销毁线程属性 API:pthread_attr_init/pthread_attr_destroy,在 acl 库中的对应形式:acl_pthread_attr_init/acl_pthread_attr_destroy

/** * 初始化创建线程时的属性对象,该 API 会赋一些缺省值给属性对象,用户若想 * 改变属性中的某个缺省值,可以通过 pthread_attr_setxxx 之类的 API 设定 * @param attr {pthread_attr_t*} 线程属性对象的指针,该指针指向的空间 *    必须由用户自己分配 * @return {int} 成功则返回 0,否则返回非 0 值 */int pthread_attr_init(pthread_attr_t *attr);/** * 销毁由 pthread_attr_init 创建的一些线程属性资源 * @param attr {pthread_attr_t*} 线程属性对象指针 * @return {int} 成功则返回 0,否则返回非 0 值 */int pthread_attr_destroy(pthread_attr_t *attr);

      在调用 pthread_attr_init 时,内部会对线程属性对象创建一些临时内存资源,所以当不需要线程属性时,需要调用 pthread_attr_destroy 来释放之。

      下面的两个 API 可以设定创建时的一些特殊属性:

3)设定创建线程为分离状态:int pthread_attr_setdetachstate(pthread_attr_t *attr, int detached),在 acl 库中的表现形式:int acl_pthread_attr_setdetachstate(acl_pthread_attr_t *attr, int detached);

/** * 设定所创建线程是否处于分离模式,当父线程创建一个子线程时指定了所创建 * 子线程为可分离模式,则父线程不必接管子线程的退出状态,否则父线程必须 * 调用 pthread_join 来接管子线程的退出状态以避免资源泄露 * @param attr {pthread_attr_t*} 线程属性对象 * @param detached {int} 非 0 表示采用线程分离模式 * @return {int} 返回 0 表示成功,否则表示出错 */int pthread_attr_setdetachstate(pthread_attr_t *attr, int detached);

 4)设定线程创建时线程堆栈大小属性:int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize),在 acl 库中的表现形式:int acl_pthread_attr_setstacksize(acl_pthread_attr_t *attr, size_t stacksize)。

/** * 该函数设定所创建线程的堆栈大小 * @param attr {pthread_attr_t*} 线程属性对象 * @param stacksize {size_t} 新创建线程的堆栈大小(单位为字节, *    在LINUX 下默认堆栈一般是 2MB) * @return {int} 返回 0 表示成功 */int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

 5)当创建的子线程为非分离状态时父线程接管子线程退出状态:int pthread_join(pthread_t thread, void **thread_return) ,在 acl 库中的表现形式为:int acl_pthread_join(acl_pthread_t thread, void **thread_return)。

/** * 当所创建的子线程采用非分离方式创建时,则父线程应该调用本 API * 来接管子线程的退出状态,否则会造成资源泄露 * @param thread {pthread_t} 子线程的线程号 * @param thread_return {void**} 该指针地址指向子线程退出 *   前返回的内存地址 * @return {int} 返回 0 表示成功,否则表示失败 */int pthread_join(pthread_t thread, void **thread_return);

       在创建线程前通过 pthread_attr_setdetachstate API 给线程属性设定了将要创建的子线程为分离状态,还有另外一个 API 可以当子线程创建后再指定子线程为分离状态:

 6)子线程创建成功后设定子线程的分离状态:int pthread_detach(pthread_t thread),在 acl 库中的表现形式为:int acl_pthread_detach(acl_pthread_t thread)。

/** * 子线程创建成功后调用本函数设定子线程为分离模式,调用本函数后, * 父线程禁止再调用 pthread_join 接管子线程的退出状态 * @param thread {pthread_t} 所创建的子线程的线程号 * @return {int} 返回 0 表示成功,否则表示失败 */int pthread_detach(pthread_t thread);

 7)线程中获得自身的线程 ID 号:pthread_t pthread_self(void),在 acl 库中的表现形式为:unsinged long acl_pthread_self(void)。

/** * 返回当前线程的线程号 * @return {pthread_t} */pthread_t pthread_self(void);

 

      以上介绍了有关 Posix 标准线程的一些常用 API,下面举一个简单的例子来说明上面 API 的使用。  

三、例子

 

#include <pthread.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>static void *mythread_main(void *arg){char *ptr = (char*) arg;printf("my thread id: %ld\r\n", pthread_self());printf("arg: %s\r\n", ptr);free(ptr);  /* 释放在父线程中分配的内存 */ptr = strdup("thread exit ok");return ptr;}int main(void){char *name = strdup("thread_test");pthread_t tid;pthread_attr_t attr;/* 初始化线程属性对象 */if (pthread_attr_init(&attr) != 0) {  /* 此处出错应该是内存资源不够所至 */printf("pthread_attr_init error: %s\r\n", strerror(errno));return 1;}/* 设定子线程的堆栈空间为 4MB */if (pthread_attr_setstacksize(&attr, 4096000) != 0) {printf("pthread_attr_setstacksize error: %s\r\n", strerror(errno));pthread_attr_destroy(&attr);  /* 必须释放线程属性资源 */return 1;}/* 创建子线程 */if (pthread_create(&tid, mythread_main, name) != 0) {printf("pthread_create error: %s\r\n", strerror(errno));pthread_attr_destroy(&attr);  /* 必须释放线程属性资源 */return 1;}printf("ok, create thread id: %ld\r\n", tid);/* 接管子线程的退出状态 */if (pthread_join(&tid, &ptr) != 0) {printf("pthread_join error: %s\r\n", strerror(errno));pthread_attr_destroy(&attr);  /* 必须释放线程属性资源 */return 1;}printf("child thread exit: %s\r\n", ptr);free(ptr);  /* 释放在子线程分配的内存 */pthread_attr_destroy(&attr);  /* 释放线程属性资源 */return 0;}

      上述例子中,只需把 pthread_ 前添加前缀 acl_,同时包含头文件 #include "lib_acl.h",该例子便可以在 WIN32 平台下运行了。

      本节暂且说这一些有关线程编程时用到的 API,下一节继续。

本文地址

acl 库下载:https://sourceforge.net/projects/acl/

个人微博:http://weibo.com/zsxxsz

0 0