一、什么是线程
1.进程:一个正在执行的程序,它是资源分配的最小单位。
2.线程:轻量级进程,程序执行的最小单位,程序独立调度和分配CPU的基本单位,它是进程中的一个实体。
一个进程中可以有多个线程,共享进程的所有资源,线程本身只包含一点必不可少的资源。
3.并发:同一时刻只能有一条指令执行,但多个进程指令被快速切换,宏观上感觉多个进程同时执行的效果。
并行:同一时刻多条指令在多个处理器上同时执行。真正的同时发生。
同步:彼此有依赖关系的调度不应该同时发生,同步就是阻止这些同时发生的事情。
异步:事情独立发生。
4.多线程的优势:
a. 占用少的系统资源,相对于多进程来说;
b. 模块化编程,能更清晰的表达程序中独立事件的关系,结构清晰;
c. 在等待慢速IO时,程序可以执行其他操作,提高并发性;
d. 多处理中开发程序的并发性;
多线程不一定在多处理器上。
二、线程的创造和生命
线程 进程
标识符类型 pthread_t pid_t
获取ID pthread_self() getpid()
创建 pthread_create() fork()
注意:pthread_t在linux中是unsigned long int类型
2.pthread_self的使用;
3.pthread_create
错误码查看:cat /usr/include/asm-generic/errno.h
4.进程结束,进程内的所有线程将终止,可以通过调用pthread_exit函数等待所有线程结束才终止。
主线程的参数是argc,argv;普通线程参数void *;
主线程默认堆栈上运行,长度足够;普通线程的堆栈受限,溢出将出错。
5.主线程随着进程创建而创建,普通线程通过pthread_create创建。注意,新线程可能在pthread_create返回前就运行了,甚至运行完毕。
6.线程的状态
a. 就绪状态:线程能够运行,但是在等待可用的处理器; //线程创建时处于就绪,或解除阻塞
b. 运行状态:线程正在运行,在多核系统中,可能同时有多个线程运行; //处理器选择了一个线程,马上运行
c. 阻塞:线程在等待处理器意外的其他条件 //比如加锁已被锁住的互斥量
d. 终止:线程从启动函数中返回,或者调用pthead_exit,或者被取消。 //
- 资源回收
线程的分离属性:分离一个线程会通知系统当该线程结束时,其所属的资源可以被回收;没有分离的线程终止时,会保留它的虚拟内存(堆栈,其他内存空间)。创建线程默认非分离的。
终止分离线程时,会释放所有系统资源,但是你必须释放由该线程占有的程序资源。malloc,mmap分配的内存可以在任何时候由任何线程释放。条件变量、互斥量、信号灯可以由线程销毁,但是如果被锁住是无法释放的, 需要先解锁
三、线程控制
1.线程的终止:
a. 进程调用exit,整个进程终止,谨慎使用。
b. 线程退出方法:启动例程返回;被同一进程中的其他线程终止;线程调用pthread_exit退出。
2.线程连接:
a. pthread_join:阻塞,直到指定线程退出; //要求调用该函数的线程是非分离的,如果是分离的,则掉用失败。
b. pthread_detach分离线程。
3.线程取消:
线程取消函数:pthrad_cancel,只是意味着发送了取消请求,是不管成功与否的。
pthead_setcancelstate设置线程取消信号的响应方式,enable或是disable。
取消类型:立刻取消,还是延时取消pthread_setcanceltype
取消点:被取消的线程会检查是否有取消的地方就是取消点,很多地方包含取消点。
4.线程发送信号pthread_kill,布局信号处理方式sigaction函数。
5.清除操作
注册/销毁清理函数
pthread_cleanup_push/pthread_cleanup_pop成对出现,否则编译出错。
四、线程创建与线程属性设置API
#include <pthread.h>
//创建线程函数原型
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
参数:
thread :新线程的TID
attr: 线程属性
start_routine: 线程例程
arg:线程例程的参数(可以是结构体)
返回值:成功0/失败errno
//获取、设置线程的分离属性函数原型(缺省状态是接合)
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
参数:
attr:线程属性变量
detachstate:PTHREAD_CREATE_DETACHED(分离)/PTHREAD_CREATE_JOINABLE(接合)
返回值:成功0/失败errno
例程
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
void *pthread1(void *arg) //线程tid1
{
while(1)
{
sleep(1);
printf("pthread1:%s\n", (char *)arg);
}
}
void *pthread2(void *arg) //线程tid2
{
while(1)
{
sleep(1);
printf("pthread222:%s\n", (char *)arg);
}
}
int main(int argc, void *argv[])
{
int i = 0;
char buf[20] = {0};
pthread_t tid1, tid2;
//Set pthread attribute
pthread_attr_t attr; //定义一个线程属性变量
pthread_attr_init(&attr); //初始化线程属性变量
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); //设置线程分离属性
pthread_create(&tid1, &attr, pthread1, (void *)buf);//add attribute attr //创建线程tid1并设置器属性为分离
pthread_create(&tid2, NULL, pthread2, (void *)buf); //创建线程tid2默认属性非分离
printf("tid1:%ld tid2:%ld\n", tid1, tid2);
while(1)
{
sprintf(buf, "write to pthread1 %d", i++);
sleep(1);
sprintf(buf, "write to pthread2 %d", i++);
sleep(1);
}
}