线程
创建线程:pthread_create函数。在线程创建以后,就开始运行相关的线程函数,在该函数运行完之后,该线程就退出了。另一种退出线程的方法是使用函数pthread_exit,这是线程的主动行为。
pthread_join可以用于将当前线程挂起,等待线程的结束。
线程创建和退出
pthread_creat函数语法要点 | |
所需头文件 | #include<pthread.h> |
函数原型 | intpthread_create (pthread_t * thread, pthread_attr_t * attr, void *( * start_routine) (void *), void arg) |
函数传入值 | thread:线程标识符。 |
| |
start_routine:线程函数的起始地址。 | |
| |
函数返回值 | 成功:0 |
| |
pthread_exit函数语法要点 | |
所需头文件 | #include<pthread.h> |
函数原型 | voidpthread_exit (void * retval) |
函数传入值 | retval:pthread_exit()调用者线程的返回值,可由其他函数如pthread_join来检查获取。 |
pthread_join函数语法要点 | |
所需头文件 | #include<pthread.h> |
函数原型 | intpthread_join (pthread_t thread, void ** thread_return) |
函数传入值 | thread:等待线程的标识符. |
|
例子:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include</usr/include/pthread.h>
voidthread1()
{
intcount=0;
for(count=0;count<6;count++) {
printf("thisis a pthread_1\n");
if(2== count)
pthread_exit(0);
sleep(1);
}
}
voidthread_2()
{
intcount;
for(count=0;count<3;count++)
printf("thisis pthread 2");
pthread_exit(0);
}
intmain()
{
pthread_tid1,id2;
intret;
ret= pthread_create (&id1,NULL,(void *)thread1,NULL);
if(0 != ret) {
printf("create pthread error \n");
exit(1);
}
ret= pthread_create (&id2, NULL, (void *) thread_2, NULL);
if(0 != ret) {
printf("Create pthread error!\n");
exit(1);
}
pthread_join(id1, NULL);
pthread_join(id2, NULL);
exit(0);
}
编译时会出现错误::对‘pthread_create’未定义的引用,开始搜索的时候,知道缺少连-lpthread该库支持,使用:gcc-o thread -lpthread thread.c
仍然报出一样的错误。后面mangcc才知道Usage:gcc [options] file...
因此需要将库链接放在末尾。gcc-o thread thread.c -lpthread
线程属性:
pthread_create函数的第二个参数—线程的属性。系统默认为非绑定、非分离、缺省1M的堆栈、与父进程同样级别的优先级。
绑定属性:
绑定属性可以保证在需要的时刻总是有一个内核线程与之对应。而非绑定属性是指用户线程和内核线程关系不是始终固定的。是由系统来控制分配的。
分离属性:
分离属性决定一个线程以什么方式来终止自己,在非分离情况下,当一个线程结束时,它所占用的系统资源并没有释放,也就是没有真正的终止。只有当pthread_join函数返回时,创建的线程才释放自己占用的系统资源。而分离属性情况下,一个线程结束时立即释放它所占有的系统资源。
这些属性的设置都是通过一定的函数来完成的,通常首先调用pthread_attr_init函数进行初始化,之后再调用相应的属性设置函数。
设置绑定属性的函数为pthread_attr_setscope,设置线程分离属性的函数为pthread_attr_setdetachstate,设置线程优先级的相关函数为pthread_attr_getschedparam(获取线程优先级)和pthread_attr_setschedparam(设置线程优先级)。在设置完这些属性后,就可以调用pthread_create函数来创建线程了。
pthread_attr_init函数语法要点 | ||
所需头文件 | #include<pthread.h> | |
函数原型 | intpthread_attr_init (pthread_attr_t * attr) | |
函数参数 | attr:线程属性 | |
函数返回值 | 成功:0 | |
| 出错:-1 | |
pthread_attr_setscope函数语法要点 | ||
所需头文件 | #include<pthread.h> | |
函数原型 | intpthread_attr_setscope (pthread_attr_t * attr, int scope) | |
函数参数 | attr:线程属性 | |
| scope | |
| ||
函数返回值 | 成功:0 | |
| 出错:-1 | |
pthread_attr_setdetachstate函数语法要点 | ||
所需头文件 | #include<pthread.h> | |
函数原型 | intpthread_attr_setdetachstate (pthread_attr_t * attr, intdetachstate) | |
函数参数 | attr:线程属性 | |
| detachstate | |
| ||
函数返回值 | 成功:0 | |
| 出错:-1 |
pthread_attr_getschedparam函数语法要点 | |
所需头文件 | #include<pthread.h> |
函数原型 | intpthread_attr_getschedparam (pthread_attr_t * attr, structsched_param * param) |
函数参数 | attr:线程属性 |
| |
函数返回值 | 成功:0 |
| |
pthread_attr_getschedparam函数语法要点 | |
所需头文件 | #include<pthread.h> |
函数原型 | intpthread_attr_setschedparam (pthread_attr_t * attr, struct_param *param) |
函数参数 | attr:线程属性 |
| |
函数返回值 | 成功:0 |
|
线程访问控制:
互斥锁 mutex
互斥锁的操作主要包括以下几个步骤:
互斥锁初始化:pthread_mutex_init
互斥锁上锁:pthread_mutex_lock
互斥锁判断上锁:pthread_mutex_trylock
互斥锁接锁:pthread_mutex_unlock
消除互斥锁:pthread_mutex_destroy
互斥锁可以分为快速互斥锁、递归互斥锁和检错互斥锁。这三种锁的区别主要在于其他未占有互斥锁的线程在希望得到互斥锁时的是否需要阻塞等待。
快速锁是指调用线程会阻塞直至拥有互斥锁的线程解锁为止。
递归互斥锁能够成功地返回并且增加调用线程在互斥上加锁的次数。
检错互斥锁则为快速互斥锁的非阻塞版本,它会立即返回并返回一个错误信息。
pthread_mutex_init函数语法要点 | ||
所需头文件 | #include<pthread.h> | |
函数原型 | intpthread_mutex_init (pthread_mutex_t * mutex, constpthread_mutexattr_t * mutexattr) | |
函数参数 | Mutex:互斥锁 | |
| Mutexattr | |
| ||
| ||
函数返回值 | 成功:0 | |
| 出错:-1 |
pthread_mutex_lock函数语法要点 | |
所需头文件 | #include<pthread.h> |
函数原型 | intpthread_mutex_lock (pthread_mutex_t * mutex) |
| |
intpthread_mutex_unlock (pthread_mutex_t * mutex) | |
| |
函数参数 | Mutex:互斥锁 |
函数返回值 | 成功:0 |
|