所谓最简单的多线程编程,就是通过pthread_create,pthread_join,pthread_exit 3个api实现线程的创建与终止,而创建的线程只做些简单的工作,如printf一些文字信息。
使用pthread_create,pthread_join,pthread_exit 进行多线程编程的模型如下图所示:
![](https://img-my.csdn.net/uploads/201212/16/1355624226_3909.png)
1 pthread_create
/**
* @function int pthread_create(pthread_t * thread, const pthread_attr_t * attr, void * (*start_routine)(void *), void *arg)
* 按照给定的线程属性attr,在一个进程(process)里创建一个新的线程(thread)
* @param attr:
* 如果attr为NULL,则内部使用默认的属性创建线程。如果在创建线程之后修改attr,则不会对已经创建的线程产生作用。
* @param thread:
* 创建线程成功后,将thread id存储在thread里,返回给调用者。否则thrad的值是未定义的。
* @param start_routine:
* 线程创建成功后,开始执行线程的入口函数start_routine。
* @param arg:
* 调用者通过arg指定线程入口函数start_routine专用的参数指针。
* @return :
* 0 创建成功返回0
* EAGAIN 超出了系统限制,如创建的线程太多,一个进程最多创建线程个数PTHREAD_THREADS_MAX。
* EINVAL attr 的值无效
* @note pthread_create创建线程后,线程入口函数即开始执行,不需要显示控制start_routine开始执行。
* 如果确实需要将此过程分为create和start2步来控制start_routine稍后执行,
* start_routine可以通过等待一个条件变量(condition variable)进行同步的方式实现。
*/
2 pthread_exit
/**
* @function void pthread_exit(void *status)
* 终止调用者线程,
* @param status:
* 通过status设置退出状态,与pthread_join配对使用
* @return :
* 无返回值,也不返回到其调用方。
* @note
* 如果调用线程尚未分离,则线程ID 和status 指定的退出状态将保持不变,直到应用程序调用pthread_join() 以等待该线程。
* 否则,将忽略status。线程ID 可以立即回收。
*/
3 pthread_join
/**
* @function int pthread_join(pthread_t thread, void **status);
* 等待thread线程终止
* 如果thread指代的线程还没有终止,将导致调用线程挂起,直到thread指代的线程终止为止。
* @param thread:
* 所等待的的终止线程
* @param status:
* 如果status的值不等于NULL,那么它的值是通过pthread_exit传递过来的。
* @return :
* 0 线程已经终止
* ESRCH 多个线程不能等待同一个线程完成,否则仅有一个线程会成功完成。其他线程将终止,并返回ESRCH 错误。
* EINVAL 一般表示thread是无效的参数
* EDEADLK 检查到死锁状态
* @note
* 如果调用线程尚未分离,则线程ID 和status 指定的退出状态将保持不变,直到应用程序调用pthread_join() 以等待该线程。
* 否则,将忽略status。线程ID 可以立即回收。
*/
4 最简单的pthread多线程hello world示例
- 使用pthread多线程库,通过main 主线程创建 5个子线程
- 每个子线程的工作相同,就是打印出“pthread's Hello World!”
- main主线程等待5个子线程全部退出后,main主线程退出(整个程序退出)。
5 关键代码
void *hello_world_thread(void *arg)
{
printf("pthread's Hello World!\n");
pthread_exit(NULL);
return NULL;
}
pthread_create(&threads[i], NULL,hello_world_thread, NULL);
pthread_join(threads[i], NULL);
完整代码,请下载 hello.c
6 运行结果
通过程序的运行结果,可以确认
- 确实创建了5个子线程,分别打印了pthread's Hello World!
- 主线程等待了5个子线程退出之后才退出
但是我不能确认5个子线程的执行顺序,即“pthread's Hello World!”分别是由哪个子线程打印的,从运行结果上是无法确认的。