概念:线程是进程中的一个执行流程
线程是cpu进行调度的基本单元(调度一段代码的执行是通过线程来完成的);进程是系统进行资源分配的基本单元。Linux下一个进程中是可以存在多个pcb的,一个pcb就是一个执行流程。
总之:线程是什么:cpu调度执行的基本基本单元(linux下通过pcb实现) 线程与进程区别:从资源和调度上进行区别 多任务处理中多进程与多线程的优缺点:健壮性,通信灵活性,创建与销毁的成本,切换调度成本
线程如何独立运行(线程间的独立数据(栈。上下文数据,errno,信号屏蔽字)与共享数据(虚拟地址空间,文件信息)
在多任务处理中,启动多少多执行流比较合适?线程控制: 线程(创建,终止,等待,分离)
创建线程:
功能:创建一个新的线程
原型
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);
参数
thread:返回线程ID
attr:设置线程的属性,attr为NULL表示使用默认属性
start_routine:是个函数地址,线程启动后要执行的函数
arg:传给线程启动函数start_routine的参数
返回值:成功返回0;失败返回错误码
例如:
线程的查看:ps-l 选项进行查看(查看的是轻量级的进程信息)
pthread_create接口的第一个参数获取到的tid,并不是轻量级进程的lwp/pid
功能:线程终止
原型
void pthread_exit(void *value_ptr);
参数
value_ptr:value_ptr不要指向一个局部变量。
返回值:无返回值,跟进程一样,线程结束的时候无法返回到它的调用者(自身
功能:取消一个执行中的线程
原型
int pthread_cancel(pthread_t thread);参数
thread:线程ID
返回值:成功返回0;失败返回错误码
功能:等待线程结束
原型
int pthread_join(pthread_t thread, void **value_ptr);参数
thread:线程ID
value_ptr:它指向一个指针,后者指向线程的返回值
返回值:成功返回0;失败返回错误码
分离线程
int pthread_detach(pthread_t thread);//设置指定线程分离属性为datach
接口:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER//互斥锁变量类型
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t
*restrict attr);//初始化
参数:
mutex:要初始化的互斥量,互斥锁变量的地址
attr:NULL//互斥锁变量属性
//在访问资源前加锁
int pthread_mutex_lock(pthread_mutex_t *mutex);//阻塞加锁,加不上则一直等待
int pthread_mutex_trylock(pthread_mutex_t *mutex);/非阻塞加锁,加不上则立即报错返回
//访问资源完毕解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);/非阻塞加锁,加不上则立即报错返回
返回值:成功返回0,失败返回错误号
//销毁
int pthread_mutex_destroy(pthread_mutex_t *mutex)//销毁互斥锁
代码演示:
常见锁概念 :
死锁:死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的 资源而处于的一种永久等待状态
避免:1银行家算法2死锁检测算法
条件变量和互斥锁搭配使用
接口:
初始化
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict
attr);
参数:
cond:要初始化的条件变量
attr:NULL
阻塞接口//条件变量和互斥锁搭配使用,体现在阻塞
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
参数:
cond:要在这个条件变量上等待
mutex:互斥量
唤醒等待
int pthread_cond_broadcast(pthread_cond_t *cond);//唤醒至少一个阻塞队列中的线程
int pthread_cond_signal(pthread_cond_t *cond);//唤醒所有阻塞队列中的线程
int pthread_cond_destroy(pthread_cond_t *cond)//销毁窗口
例子:
#include<stdio.h>
2 #include<pthread.h>
3 int counter=0;//0表示没有饭,1表示有饭
4 pthread_mutex_t mutex;
5 pthread_cond_t cond;
W> 6 void *curstomer(void*arg)
7 {
8 while(1)
9 {
10 pthread_mutex_lock(&mutex);
11 if(counter==0)//
12 {
13 pthread_cond_wait(&cond,&mutex);
14 }
15 printf("好吃,再来一碗\n");
16 counter=0;//吃完了就没饭了
17 pthread_cond_signal(&cond);//唤醒厨师
18 pthread_mutex_unlock(&mutex);//解锁
19 }
20 return 0;
21 }
W> 22 void *cook(void *arg)
23 {
24 while(1)
25 {
26 pthread_mutex_lock(&mutex);
27 if(counter==1)
28 {
29 pthread_cond_wait(&cond,&mutex);
30 }
31 printf("饭好了,快来吃\n");
32 counter=1;
33 pthread_cond_signal(&cond);
34 pthread_mutex_unlock(&mutex);
}
36 return 0;
37 }
38 int main()
39 {
40 pthread_t cus_tid,cook_tid;
41 int ret;
42 pthread_mutex_init(&mutex,NULL);
43 pthread_cond_init(&cond,NULL);
44 pthread_cond_init(&cond,NULL);
45 ret=pthread_create(&cus_tid,NULL,curstomer,NULL);
46 if(ret!=0)
47 {
48 printf("pthread_creat error\n");
49 return -1;
50 }
51 ret=pthread_create(&cook_tid,NULL,cook,NULL);
52 if(ret!=0)
53 {
54 printf("pthread_create error\n");
55 return -1;
56 }
57 pthread_join(cus_tid,NULL);
58 pthread_join(cook_tid,NULL);
59 pthread_mutex_destroy(&mutex);
60 pthread_cond_destroy(&cond);
62 return 0;
63 }
交替阻塞,交替唤醒的过程。若修改代码实现多对多,例如:
pthread_t cus_tid[4],cook_tid[4];;
会出现卡死的情况。原因在于:
修改后的代码如下:
13 {
14 pthread_cond_wait(&cond_cus,&mutex);
15 }
16 printf("好吃,再来一碗\n");
17 counter--;//吃完了就没饭了
18 pthread_cond_signal(&cond_cook);//唤醒厨师
19 pthread_mutex_unlock(&mutex);//解锁
20 }
21 return 0;
22 }
23 void *cook(void *arg)
24 {
25 while(1)
26 {
27 pthread_mutex_lock(&mutex);
28 while(counter>0)
29 {
30 pthread_cond_wait(&cond_cook,&mutex);
31 }
32 printf("饭好了,快来吃\n");
33 counter++;
34 pthread_cond_signal(&cond_cus);
pthread_mutex_unlock(&mutex);
36 }
37 return 0;
38 }
39 int main()
40 {
41 pthread_t cus_tid[4],cook_tid[4];;
42 int ret;
43 pthread_mutex_init(&mutex,NULL);
44 pthread_cond_init(&cond_cus,NULL);
45 pthread_cond_init(&cond_cook,NULL);
46 for(int i=0;i<4;i++)
47 {
48
49
50 ret=pthread_create(&cus_tid[i],NULL,curstomer,NULL);
51 if(ret!=0)
52 {
53 printf("pthread_creat error\n");
54 return -1;
55 }
56 ret=pthread_create(&cook_tid[i],NULL,cook,NULL);
57 if(ret!=0)
58 {
59 printf("pthread_create error\n");
60 return -1;
61 }
生产者消费者模型优点 :解耦、支持并发、支持忙闲不均
#include <semaphore.h>//头文件
sem_t sem 信号量变量类型
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数:
pshared:0表示线程间共享,非零表示进程间共享(进程间), 0线程间
value:信号量初始值
p操作:
功能:等待信号量,会将信号量的值减1
int sem_wait(sem_t *sem);//阻塞接口
int sem_trywait(sem_t *sem);//非阻塞接口
int sesm_timedwait(sem_t *sem,struct timespec *soec);//阻塞但有限制时长
v操作:
功能:发布信号量,表示资源使用完毕,可以归还资源了。将信号量值加1。
int sem_post(sem_t *sem);
//销毁
int sem_destroy(sem_t *sem)
线程池:
多线程:
线程概念:线程是什么?
进程与线程进行多任务处理的不同之处?
线程间的共享与独有
线程控制:等待与分离是什么?
线程安全:
概念:线程安全是什么?实现:同步与互斥(概念)
互斥的实现--互斥锁:互斥锁实现互斥的原理?
死锁:概念-死锁是什么? 如何产生的?如何预防?如何避免?
同步的实现--条件变量&信号量(各自的本质是什么)
生产者与消费者模型:应用场景,优点,实现