多线程(系统编程最重要的)--必考

【面试题】在多线程这一块的考点有:
*谈谈你对线程的理解
*线程与进程的区别
*线程安全
首先我们来初步认识一下线程,在Linux下线程是用进程来模拟的,这个pcb既描述了进程又描述了进程,所以我们称这个线程为轻量级进程。但是在其他操作系统下进程和线程的描述是不同的,Linux下进程是一个线程组。
一、线程的概念
1.概念
在这里插入图片描述
在这里插入图片描述
2、进程和线程哪个好(进程和线程的区别)
线程的优点:(这些优点都是因为使用同一个虚拟地址空间)
(1)线程的创建/销毁成本更低
(2)线程间通信更加便捷
(3)线程的调度成本更低(因为只需要切换pcb就好)
(4)线程的执行粒度更细致
线程的缺点:
(1)因为缺乏访问控制,因此编码的时候需要的问题更多
(2)稳定性低
最后这个问题的答法就是:分别说一下线程的优缺点,具体情况视情况定论
二、线程控制
因为操作系统并没有提供线程控制的函数接口,但是有一群大佬们对于线程控制编写了一套库函数提供我们使用。
因为线程的接口代码和数据都在用户空间(共享区),因此也说我们使用这套接口创建的线程是用户态多线程,但是线程在我们操作系统内部对应了一个轻量级进程作为执行调度的载体。
1.线程的创建
(1)演示线程的创建

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<thread.h>
int main(){
void *thr_start(void *arg){
pthread_t tid=(pthread_t)arg;
while(1){
printf("I am a common thread\n");
sleep(1);
}
}
//int pthread_create(pthread_t *thread,pthread_attr_t *attr,void *(*start_routine)(void *arg));
//thread:输出型参数,用于获得用户态线程id
attr:通过线程的入口函数,传递给线程的参数
//返回值:成功-0,失败-非0
pthread_t tid;
int ret==pthread_create(&tid,NULL,thr_start,(void*)tid);
if(ret!=0){
printf("pthread create error");
return -1;
}
printf("common thread id:%u\n",tid);
while(1){
printf("I am main thread\n");
sleep(1);
}
return 0;
}

(2)三个id
在这里插入图片描述
(3)线程数据的独有与共享
(一定要明白线程地址空间一定在进程虚拟地址空间中)
在这里插入图片描述
2.线程终止
(1)方式:
return,但是主线程中(main函数中)不能return
pthread_exit:谁调用谁退出
pthread_cancel:让别人退出
注意:对于同一个进程下的主线程和普通线程,它们没有父子关系,但是当main线程退出后,common线程就会变成僵尸进程。
3.线程的等待——等待指定线程退出
(1)等待的原因:线程退出后,为了保存退出返回值,因此操作系统不会自定回收资源,需要其他线程等待直到获取到返回值,并允许操作系统回收资源;如果不等待就会造成内存泄漏。
(2)线程的分离:设置线程的分离属性,被设置的线程退出后将自动回收资源,不需要等待。线程如果处于detach状态(通过pthread detach设置),则线程不能被等待。如果线程被取消则返回值是——PTHREAD_CANCELED-1;如果线程不是joinable状态,这时候如果等待就会报错(EINVAL)。
三、线程安全【面试一定会考】
1.概念:线程之间对临界资源的安全访问。因为CPU资源足够的情况下,多个线程的运行可能是并行的,因此对临界资源的访问,就有可能造成争抢操作,然而这种争抢操作会造成数据的二义性问题。因此,线程安全就是讨论如何保证对临界资源的安全访问。
2.解决办法:同步与互斥
同步:对临界资源同时间的时序可控性
互斥:对临界资源同一时间的唯一性访问
3.如何实现线程间的同步与互斥【特别重要】
在这里插入图片描述
(1)互斥的实现——互斥锁
互斥锁:只有0/1的计数器;但是互斥锁这个计数器的操作必须是原子操作。
1-有资源能操作
0-没资源则阻塞

猜你喜欢

转载自blog.csdn.net/ZhuiZhuDream5/article/details/88139714