多线程编程API简介 上

一、概述

      本文主要讲述了 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

C代码   收藏代码
  1. /** 
  2.  * 创建独立的线程,使处理任务在该线程中运行,线程运行完毕,该线程的创建者 
  3.  * 可以接收该线程的退出返回值 
  4.  * @param tid {pthread_t*} 当线程创建成功时,该变量所指内存区域存储线程 
  5.  *    的线程 ID 号 
  6.  * @param attr{pthread_attr_t*} 创建线程的属性,该属性里可以设定线程的 
  7.  *    堆栈大小、是否与创建线程分离等 
  8.  * @param start_routine {void *(*)(void*)} 线程成功创建后开始运行的函数指针, 
  9.  *    该函数指针是用户应用的功能函数入口,函数的参数也由用户指定 
  10.  * @param arg {void*} start 函数运行时传入的参数,该参数由用户设定 
  11.  * @return {int} 线程创建是否成功,返回 0 表示成功,否则表示失败 
  12.  * 
  13.  */  
  14. 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

C代码   收藏代码
  1. /** 
  2.  * 初始化创建线程时的属性对象,该 API 会赋一些缺省值给属性对象,用户若想 
  3.  * 改变属性中的某个缺省值,可以通过 pthread_attr_setxxx 之类的 API 设定 
  4.  * @param attr {pthread_attr_t*} 线程属性对象的指针,该指针指向的空间 
  5.  *    必须由用户自己分配 
  6.  * @return {int} 成功则返回 0,否则返回非 0 值 
  7.  */  
  8. int pthread_attr_init(pthread_attr_t *attr);  
  9.   
  10. /** 
  11.  * 销毁由 pthread_attr_init 创建的一些线程属性资源 
  12.  * @param attr {pthread_attr_t*} 线程属性对象指针 
  13.  * @return {int} 成功则返回 0,否则返回非 0 值 
  14.  */  
  15. 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);

C代码   收藏代码
  1. /** 
  2.  * 设定所创建线程是否处于分离模式,当父线程创建一个子线程时指定了所创建 
  3.  * 子线程为可分离模式,则父线程不必接管子线程的退出状态,否则父线程必须 
  4.  * 调用 pthread_join 来接管子线程的退出状态以避免资源泄露 
  5.  * @param attr {pthread_attr_t*} 线程属性对象 
  6.  * @param detached {int} 非 0 表示采用线程分离模式 
  7.  * @return {int} 返回 0 表示成功,否则表示出错 
  8.  */  
  9. 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)。

C代码   收藏代码
  1. /** 
  2.  * 该函数设定所创建线程的堆栈大小 
  3.  * @param attr {pthread_attr_t*} 线程属性对象 
  4.  * @param stacksize {size_t} 新创建线程的堆栈大小(单位为字节, 
  5.  *    在LINUX 下默认堆栈一般是 2MB) 
  6.  * @return {int} 返回 0 表示成功 
  7.  */  
  8. 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)。

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

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

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

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

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

C代码   收藏代码
  1. /** 
  2.  * 返回当前线程的线程号 
  3.  * @return {pthread_t} 
  4.  */  
  5. pthread_t pthread_self(void);  

 

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

三、例子

 

C代码   收藏代码
  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5. #include   
  6.   
  7. static void *mythread_main(void *arg)  
  8. {  
  9.     char *ptr = (char*) arg;  
  10.   
  11.     printf("my thread id: %ld\r\n", pthread_self());  
  12.     printf("arg: %s\r\n", ptr);  
  13.     free(ptr);  /* 释放在父线程中分配的内存 */  
  14.   
  15.     ptr = strdup("thread exit ok");  
  16.     return ptr;  
  17. }  
  18.   
  19. int main(void)  
  20. {  
  21.     char *name = strdup("thread_test");  
  22.     pthread_t tid;  
  23.     pthread_attr_t attr;  
  24.   
  25.     /* 初始化线程属性对象 */  
  26.     if (pthread_attr_init(&attr) != 0) {  /* 此处出错应该是内存资源不够所至 */  
  27.         printf("pthread_attr_init error: %s\r\n", strerror(errno));  
  28.         return 1;  
  29.     }  
  30.   
  31.     /* 设定子线程的堆栈空间为 4MB */  
  32.     if (pthread_attr_setstacksize(&attr, 4096000) != 0) {  
  33.         printf("pthread_attr_setstacksize error: %s\r\n", strerror(errno));  
  34.         pthread_attr_destroy(&attr);  /* 必须释放线程属性资源 */  
  35.         return 1;  
  36.     }  
  37.   
  38.     /* 创建子线程 */  
  39.     if (pthread_create(&tid, mythread_main, name) != 0) {  
  40.         printf("pthread_create error: %s\r\n", strerror(errno));  
  41.         pthread_attr_destroy(&attr);  /* 必须释放线程属性资源 */  
  42.         return 1;  
  43.     }  
  44.     printf("ok, create thread id: %ld\r\n", tid);  
  45.   
  46.     /* 接管子线程的退出状态 */  
  47.     if (pthread_join(&tid, &ptr) != 0) {  
  48.         printf("pthread_join error: %s\r\n", strerror(errno));  
  49.         pthread_attr_destroy(&attr);  /* 必须释放线程属性资源 */  
  50.         return 1;  
  51.     }  
  52.   
  53.     printf("child thread exit: %s\r\n", ptr);  
  54.     free(ptr);  /* 释放在子线程分配的内存 */  
  55.   
  56.     pthread_attr_destroy(&attr);  /* 释放线程属性资源 */  
  57.     return 0;  
  58. }  

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

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

你可能感兴趣的:(多线程编程API简介 上)