一、概述
本文主要讲述了 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/
github: https://github.com/acl-dev/acl
相关推荐
本篇将深入探讨多线程编程模型,包括相关概念、操作系统提供的API以及在实际编程中遇到的问题和解决方案。 首先,我们要理解多线程中涉及的各种对象的概念。线程是执行路径或程序执行的顺序流,它是进程中的一个...
接着,书中详细讲解了C++中用于多线程编程的API,如CreateThread、_beginthreadex等,以及如何使用C++11及更新的标准库中的std::thread。这些API的使用方法和注意事项是多线程编程实践中的重要知识,书中会有具体的...
在Linux多线程编程手册中,除了对各种API进行详细说明外,也会对常见的编程模式和设计原则进行指导,例如如何处理线程同步问题、死锁避免、线程池的使用等。此外,手册可能还会讨论特定于平台的特性,例如在Linux上...
这份“JAVA多线程编程技术PDF”是学习和掌握这一领域的经典资料,涵盖了多线程的全部知识点。 首先,多线程的核心概念包括线程的创建与启动。在Java中,可以通过实现Runnable接口或继承Thread类来创建线程。创建后...
### 多线程编程指南:全面解析与应用 #### 多线程编程的定义与重要性 多线程编程是一种让程序...合理使用线程属性和同步对象,遵循良好的编程实践,可以避免常见的多线程编程陷阱,构建稳定、高效的多线程应用程序。
总的来说,本多线程编程指南是一个关于在iOS和MacOSX平台上进行多线程编程的全面资源,无论你是初学者还是有经验的开发者,都能从中获得有价值的信息和指导。虽然现代的并发编程方法,如GCD和Operation Objects提供...
MFC通过提供CWinThread类来支持多线程编程,它封装了Windows API的线程创建和管理功能。 创建MFC多线程主要涉及以下几个步骤: 1. **继承CWinThread**:首先,你需要创建一个新的C++类,并让它继承自CWinThread。...
在计算机科学领域,多线程编程是一种常见的技术手段,用于提高程序的执行效率和响应能力。通过本篇文章,我们将探讨多线程编程的基本概念及其在实际开发中的应用。 #### 二、问题背景与解决方案 假设我们正在开发一...
#### 四、多线程编程常见问题及解决策略 在实际开发过程中,可能会遇到以下几种常见问题: 1. **竞态条件**:当两个或多个线程同时访问相同的共享资源时,可能会导致数据不一致的问题。解决方法通常是使用互斥锁或...
压缩包中的"threadtech_jb51.rar"可能包含具体的多线程编程示例,如并发下载、并行计算、用户界面更新等常见应用场景。这些实例可以帮助理解如何在实际项目中有效地使用多线程。 总结,掌握VC++多线程编程不仅需要...
本文将详细介绍Linux下的多线程编程原理、基本API使用以及示例分析。 #### 二、POSIX线程(pthread) ##### 2.1 POSIX线程简介 Linux下的多线程编程基于POSIX线程标准,即pthread。该标准定义了一系列API,用于...
在IT领域,多线程编程是一项基础且重要的技术,尤其在Windows操作系统环境下。"实验一:WindowsThreads多线程编程实验"旨在让...通过仔细阅读、分析和调试这些文件,学生将能够全面掌握Windows平台上的多线程编程技巧。
死锁是多线程编程中常见的问题,当两个或更多线程相互等待对方释放资源时就会发生死锁。避免死锁的方法包括避免循环等待、设置超时、资源预分配等。此外,活锁也是需要注意的问题,即线程不断重试导致永远无法进行...
在多线程编程中,死锁和活锁是常见的问题。死锁发生在两个或更多线程互相等待对方释放资源而无法继续执行的情况。活锁则是线程不断重试导致的状态,但始终无法取得进展。了解和避免这些陷阱是编写健壮多线程程序的...
死锁是多线程编程中的一种常见问题,发生在两个或更多线程相互等待对方释放资源,从而导致所有线程都无法继续的情况。避免死锁的方法包括避免循环等待、设置超时、使用死锁检测算法等。 线程优先级也是Java多线程中...
在MFC中,多线程编程是通过CWinThread类来实现的,这个类代表了一个执行上下文,即线程。 1. **多线程基础**: 在Windows系统中,每个进程可以包含一个或多个线程。线程允许程序同时执行多个任务,提高应用程序的...
此外,死锁和饥饿是多线程编程中的两个常见问题,需要特别注意。死锁发生在两个或更多线程相互等待对方释放资源时,而饥饿则是一个线程因其他高优先级线程持续占用资源而无法获得执行。解决这些问题通常需要精心设计...