线程的概念:
线程是一个轻量级的进程,每一个线程都属于一个进程,线程是CPU任务调度的最小单元,线程为进程中的栈里面的0-8M的一小段内存空间依附于进程之上
创建:
线程空间位于进程空间内部
进程中的每个线程,栈区是独立的,共享进程中的数据区和文本区,堆区。
调度:
- 宏观并行、微观串行
线程消亡:
- 线程执行结束后,需要回收线程空间
多进程和多线程的优缺点:
执行效率:
- 多线程执行效率高(并发程度(创建速度快)和任务切换(在一个进程空间内部完成多线程任务切换))
- 多进程执行效率低
通信角度:
- 线程可以共享空间,可以直接通信(多线程间可以使用全局变量通信,因为全局变量为共享空间)
- 进程空间独立,不能直接通信(通信必须使用:管道、信号、消息队列、共享内存、信号灯等方式)
安全性:
- 多进程安全(一个进程异常结束不影响其余进程执行)
- 多线程不安全(一个线程异常结束会导致进程结束,其余线程均无法继续执行)
函数接口介绍:
线程的创建:pthread_create
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
功能:
- 创建一个线程
参数:
-
thread:存放线程ID空间首地址(线程编号)
-
attr:线程的属性(默认NULL)
-
start_routine:线程入口函数地址(函数指针)
-
arg:给线程函数的参数(如果不传值进入,则为NULL)
返回值:
- 成功返回0
- 失败返回非0值
代码示例
void *th_fun(void *arg) { while(1) { printf("i am thread\n"); sleep(1); } } int main(void) { pthread_t tid; pthread_create(&tid, NULL, th_fun, NULL); return 0; }
以上代码便实现了创建一个线程的工作,在线程中进行输出i am thread的工作,由于线程占用系统的空间并不大,所以往往都是在子线程中完成各个小分支的项目需求,而主线程未接收控制子线程,这点和进程有所区别。
线程创建注意:
- 一次pthread_create执行只能创建一个线程。
- 每个进程至少有一个线程称为主线程。
- 主进程退出则所有创建的子线程都退出。
- 主线程必须有子线程同时运行才算多线程程序。
- 线程id是线程的唯一标识,是CPU维护的一组数字。
- pstree 查看系统中多线程的对应关系。(ps -eLf )
- 多个子线程可以执行同一回调函数。
线程ID的获取:pthread_self
pthread_t pthread_self(void);
功能:
- 获取当前线程的线程id
参数:
- 无
返回值:
- 成功 返回当前线程的线程id
- 失败 -1
代码示例
void *th_fun1(void *arg) { while(1) { printf("is thread. tid = %lu\n", pthread_self()); sleep(1); } } int main(int argc, const char *argv[]) { pthread_t tid; pthread_create(&tid, NULL, th_fun1, NULL); while(1) { } return 0; }
在创建线程的代码端里多加了pthread_self();剩余没有更多改变,不过多赘述。
线程的退出:pthread_exit
void pthread_exit(void *retval);
功能:
- 子线程自行退出
参数:
- retval--线程退出时候的返回状态,临死遗言。(不能是局部变量的地址),没有想传送的就默认为NULL
返回值:
- 无
代码示例
void *th_fun1(void *arg) { int cnt = 10; while(1) { if(cnt == 0) { pthread_exit(NULL); } cnt--; printf("in thread fun. tid1 = %lu\n", pthread_self()); sleep(1); } }
以上代码为子线程的一个函数,输出子线程号10次以后自动退出,不过多赘述。
以上就为线程的基本应用,在本文的后续将会为大家介绍线程的进阶,分离以及结合性质,希望大家多多关注。