在说多线程之前,我们来回忆下栈的功能和用途:一个栈中只有最下方的帧可被读写,相应的,也只有该帧对应的那个函数被激活,处于工作状态。为了实现多线程,则必须绕开栈的限制。为此,在创建一个新线程时,需要为这个线程建一个新的栈,每个栈对应一个线程。当某个栈指向到全部弹出时,对应线程完成任务,并结束。所以多线程的进程在内存中有多个栈,多个栈之间以一定的空白区域隔开,以备栈的增长。
1. 多线程的创建与结束
- 头文件以及原型:
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); ---->创建一个线程
int pthread_join(pthread_t thread, void **retval);------>等待一个线程的结束 - 线程的结束有两种途径:
(1)函数已经结束,调用它的线程也就结束了;
(2)通过函数pthread_exit来实现。—>原型:void pthread_exit(void *retval); - pthread_join和pthread_exit的区别:
(1)pthread_join一般是主线程来调用,用来等待子线程退出,因为是等待,所以是阻塞的,一般主线程会依次添加所有它创建的子线程;
(2)pthread_exit一般是子线程调用,用来结束当前线程;
(3)子线程可以通过pthread_exit传递一个返回值,而主线程通过pthread_join获得该返回值,从而判断该子线程的退出时正常还是异常。
eg:
void *retval;
iRet = pthread_join(tid, &retval);
if(iRet){
printf(“pthread_join error: iRet = %d\n”, iRet);
return iRet;
}
printf(“retval = %ld\n”, (long)retval);
注意:犹豫本程序是在64位机器上执行的,所以指针类型和long类型大小相等,都是8byte,并且将temp强制转换成log类型,如果强制转换成int类型,编译时会提示“error: cast from ‘void *’ to ‘int’ loses precision” - 获取线程id
(1)在线程调用函数中使用pthread_self函数来获得线程id;
(2)在创建线程时生成的id。 - 线程的属性介绍
(1)线程属性结构如下:
typedef struct
{
int detachstate; //线程的分离状态
int schedpolicy; //线程调度策略
structsched_param schedparam; //线程的调度參数
int inheritsched; //线程的继承性
int scope; //线程的作用域
size_t guardsize; //线程栈末尾的警戒缓冲区大小
void* stackaddr; //线程栈的位置
size_t stacksize; //线程栈的大小
}pthread_attr_t;
(2)线程分离状态:detachstate
该属性