本文首先来讲解一下Linux多线程编程的基本概念和操作,然后编写一个测试的小例子进行实例说明。
一、多线程编程基础
我们知道,在linux系统中,进程是程序执行和资源分配的基本单位,每个进程都拥有自己的数据段、代码段和堆栈段,这就导致了进程在进行上下文切换的时候都必须进行一些相对复杂的进程上下文切换的工作。所以为了克服这个问题,进程在演化过程中出现了另一种概念——线程。它是进程内独立运行的一条线路,是处理器调度的最小单元,也可以成为轻量级进程。同一进程的线程之间对内存空间的访问和资源是共享的。因此,线程的上下文切换比进程小的多。
下面来介绍一下在多线程编程中常用的一些API:
a、创建一个线程
int pthread_create ((pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg))
thread : 创建的线程标识符
attr : 线程属性设置,通常设为NULL
start_routine : 线程运行的函数体
arg : 传递给线程运行函数体的参数
b、线程结束
返回值:0成功,其他错误
void pthread_exit(void *retval)
retval : 线程结束时传递的返回值,可以有其他线程操作相关的API来获取,比如pthread_join()
c、等待线程的函数
我们知道子线程是在主线程当中创建的,我们需要几个机制当所有子线程都执行完毕了主线程才可以退出。
int pthread_join ((pthread_t th, void **thread_return))
th : 等待的线程的标识符
thread_return : 用来存储被等待线程的返回值
d、线程取消函数
返回值:0成功,其他错误
int pthread_cancel((pthread_t th)
th : 要取消的线程的线程标识符
返回值:0成功,其他错误
二、测试
编写一个小例子进行测试,实现的功能:在主线程中创建两个子线程,等待两个子线程执行完毕,主线程才退出,具体如下面代码所示:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
/*
* 子线程a的线程体
*/
static void *start_routine_a (void *arg)
{
int loop_cnt = (int)arg;
int i;
for(i = 0; i < 5; i++)
{
printf("TECH-PRO thread A : %d\n", i);
sleep(1);
}
pthread_exit(NULL); /* 线程执行完毕 */
}
/*
* 子线程b的线程体
*/
static void *start_routine_b (void *arg)
{
int loop_cnt = (int)arg;
int i;
for(i = 0; i < 5; i++)
{
printf("TECH-PRO thread B : %d\n", i);
sleep(1);
}
pthread_exit(NULL); /* 线程执行完毕 */
}
/*
* 定义两个子线程,让两个子线程同时运行
*/
int main(void)
{
int ret;
pthread_t pthread_a, pthread_b;
/* 开始 */
printf("main : start!\n");
/* 创建两个子线程 */
ret = pthread_create(&pthread_a, NULL, start_routine_a, (void *)5);
if(0 != ret)
{
printf("pthread_create for a is failed!\n");
return -1;
}
ret = pthread_create(&pthread_b, NULL, start_routine_b, (void *)5);
if(0 != ret)
{
printf("pthread_create for b is failed!\n");
return -1;
}
/* 等待进程结束 */
pthread_join(pthread_a, NULL);
pthread_join(pthread_b, NULL);
/* 结束 */
printf("main : stop!\n");
return 0;
}
对上面程序进行编译,在编译和链接时要加入-lpthread, 结果如下所示:
从上面结果可以看出,两个子线程交替执行,主线程等待两个子线程执行完毕再退出。