Linux系统下的多线程遵循POSIX线程接口, 称为pthread. 编写Linux下的多线程程序, 需要使用pthread.h头文件, 连接时需要使用libpthread.a库( -lpthread). Linux下的pthread的实现是通过系统调用clone()来实现的.
clone()是Linux所御用的系统调用, 它的使用方式类似fork().
来看一个例子. example.c
#include<stdio.h>
#include<pthread.h>
void thread(void)
{
int i;
for(i = 0; i < 3; i++)
{
printf(" This is a pthread.\n");
}
}
int main()
{
pthread_t id;
int i, ret;
ret = pthread_create( &id, NULL, (void*)thread, NULL);//创建线程
if( ret !=0 )
{
printf("Create pthread error!\n");
exit(1);
}
for( i = 0; i < 3 ; i++)
printf(" This is the main process.\n");
pthread_join( id, NULL);
return 0;
}
编译: gcc example.c -lpthread -o example
运行: ./example
结果:
This is a pthread.
This is a pthread.
This is a pthread.
This is the main process.
This is the main process.
This is the main process.
再次运行结果:
This is a pthread.
This is the main process.
This is a pthread.
This is the main process.
This is a pthread.
This is the main process.
两次结果不一样!!这是因为两个线程争夺CPU资源的结果.使用了pthread_create 和 pthread_join两个函数, 并声明了pthread_t型变量.
pthread_t在头文件/usr/include/bits/pthreadtypes.h中定义: typedef unsigned long int pthread_t; 它是一个线程标识符.
pthread_create函数用来创建一个线程,它的原型是:extern int pthread_create __P( (pthread_t * __thread, __const pthread_attr_t * __attr, void *(* __start_routine)(void *), void *arg));
第一个参数为指向线程标识符的指针, 第二个参数用来设置线程属性, 第三个参数是线程运行函数的起始地址, 最后一个参数是运行函数的参数. 返回0时, 表示成功创建线程, 否则失败.
常见的错误返回代码为EAGAIN和EINVAL, EAGAIN表示系统限制创建新的线程, 例如线程数目过多了; EINVAL表示第二个参数代表的线程属性值非法.
pthread_join函数,用来等待一个线程的结束.原型为: extern int pthread_join __P( (pthread_t __th, void ** __thread_return));
第一参数为被等待的线程标识符, 第二个参数为一个用户定义的指针, 它可以用来存储被等待线程的返回值. 这个函数是一个线程阻塞的函数, 调用它的函数将一直等待到被等待的线程结束为止. 当函数返回时,
被等待线程的资源被收回. 一个线程的结束有两种途径, 一种函数结束, 调用它的线程也结束; 别一种方式是通过pthread_exit来实现.
pthread_exit函数的原型为: extern void pthread_exit __P( (void * __retval))__attribute__( (__noreturn) );
唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL, 这个值将被传递给thread_return.
一个线程不能被多个线程等待, 否则第一个接收到信号的线程成功返回, 其余调用pthread_join的线程则返回错误代码ESRCH.
clone()是Linux所御用的系统调用, 它的使用方式类似fork().
来看一个例子. example.c
#include<stdio.h>
#include<pthread.h>
void thread(void)
{
int i;
for(i = 0; i < 3; i++)
{
printf(" This is a pthread.\n");
}
}
int main()
{
pthread_t id;
int i, ret;
ret = pthread_create( &id, NULL, (void*)thread, NULL);//创建线程
if( ret !=0 )
{
printf("Create pthread error!\n");
exit(1);
}
for( i = 0; i < 3 ; i++)
printf(" This is the main process.\n");
pthread_join( id, NULL);
return 0;
}
编译: gcc example.c -lpthread -o example
运行: ./example
结果:
This is a pthread.
This is a pthread.
This is a pthread.
This is the main process.
This is the main process.
This is the main process.
再次运行结果:
This is a pthread.
This is the main process.
This is a pthread.
This is the main process.
This is a pthread.
This is the main process.
两次结果不一样!!这是因为两个线程争夺CPU资源的结果.使用了pthread_create 和 pthread_join两个函数, 并声明了pthread_t型变量.
pthread_t在头文件/usr/include/bits/pthreadtypes.h中定义: typedef unsigned long int pthread_t; 它是一个线程标识符.
pthread_create函数用来创建一个线程,它的原型是:extern int pthread_create __P( (pthread_t * __thread, __const pthread_attr_t * __attr, void *(* __start_routine)(void *), void *arg));
第一个参数为指向线程标识符的指针, 第二个参数用来设置线程属性, 第三个参数是线程运行函数的起始地址, 最后一个参数是运行函数的参数. 返回0时, 表示成功创建线程, 否则失败.
常见的错误返回代码为EAGAIN和EINVAL, EAGAIN表示系统限制创建新的线程, 例如线程数目过多了; EINVAL表示第二个参数代表的线程属性值非法.
pthread_join函数,用来等待一个线程的结束.原型为: extern int pthread_join __P( (pthread_t __th, void ** __thread_return));
第一参数为被等待的线程标识符, 第二个参数为一个用户定义的指针, 它可以用来存储被等待线程的返回值. 这个函数是一个线程阻塞的函数, 调用它的函数将一直等待到被等待的线程结束为止. 当函数返回时,
被等待线程的资源被收回. 一个线程的结束有两种途径, 一种函数结束, 调用它的线程也结束; 别一种方式是通过pthread_exit来实现.
pthread_exit函数的原型为: extern void pthread_exit __P( (void * __retval))__attribute__( (__noreturn) );
唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL, 这个值将被传递给thread_return.
一个线程不能被多个线程等待, 否则第一个接收到信号的线程成功返回, 其余调用pthread_join的线程则返回错误代码ESRCH.