目录
1.进程和线程的区别
windows线程和进程的底层实现不同,linux最初没有线程概念,基于进程做了线程,就是轻量级的进程和windows不同,
线程的五种状态:新建、就绪、阻塞、运行、死亡
2.1 并发与并⾏
分时复用
并发:指并发(concurrency):指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行。
cpu会把单位时间分成若干份,每一份就是一个时间片,然后由系统进行线程的调度,去抢时间片,抢到后线程由就绪态变成进行态,时间片用完后,线程恢复就绪态继续去抢下一个时间片。一直这样循环,线程其实是走走停停,宏观一起执行,微观是走走停停。cpu的执行周期都是纳秒级别,所以我们感受不到。
并⾏:指在同一时刻,有多条指令在多个处理器上同时执行,所以无论从微观还是从宏观来看,二者都是一起执行的。
⽽在多个 CPU 系统中,则这些可以并发执⾏的程序便可以分配到多个处理器上( CPU ),实现多任务并⾏ 执⾏,
注意:单核处理器的计算机肯定是不能并⾏的处理多个任务的,只能是多个任务在单个 CPU 上并发运 ⾏。同理 , 线程也是⼀样的,从宏观⻆度上理解线程是并⾏运⾏的,但是从微观⻆度上分析却是串⾏ 运⾏的,即⼀个线程⼀个线程的去运⾏,当系统只有⼀个 CPU 时,线程会以某种顺序执⾏多个线程, 我们把这种情况称之为线程调度。
进程是系统进行资源分配和调度的基本单元,而线程是进程的子任务,是最小的执行单位,是CPU分配和调度的基本单元;
一个进程可以有多个线程,一个线程只能属于一个进程
进程之间不会相互影响,多线程间如果一个线程崩溃可能会造成多个线程崩溃
进程有独立的地址空间,线程共享一个地址空间
多个线程独享栈区,共享代码区、堆区和全局区
假设启动10个线程,会有10个栈空间,每个栈和每个栈之间,互不干扰,各自执行各自的,这就是多线程并发。
3.进程间的通信(Scoket)
套接字
介绍;windows 需要加载套接字库然后释放资源,linux则不需要
一次性检测的客户端请求;
客户端:
socket套接字创建之后通过connect函数进行初始化,这样就知道如何连接服务器,指定服务器的IP地址和端口,就是服务器函数bind()绑定的IP地址和端口
connect函数会位客户端随机生成一个没有被占用的IP地址和端口
服务器:
socket套接字创建之后
bind()绑定IP地址和端口 用add_any函数可以自动识别主机地址
listen监听(文件描述符,最多128个请求)
阻塞并等待客户端的连接accept
接收数据用recv函数判断接受到的数据是否为0
客户端send recive 阻塞 是读写缓冲区写满了
服务器send receive阻塞是读写缓冲区无数据 无数据一直阻塞
4. 线程之间通信:
多线程进行工作时,是分时复用CPU的时间片,哪个线程抢到了,谁就执行
1.互斥锁
pthread_mutex_init 对互斥锁进行初始化,用restrict来修饰指针,指向互斥锁变量的地址,只有关键字修饰的指针可以访问内存地址,
2.读写锁
p_thread_t p;
pthread_rwlock_t p1;
pthread_rwlock_init(&p1,null);
3.条件变量
条件变量是用来阻塞线程,多线程中条件变量需要配合互斥锁,才能实现线程的同步
条件变量是只有满足条件才会阻塞线程,主要用来生产者、消费者模型,
生产者-若干线程 消费者-若干线程 任务队列-数组链表stl容器各种数据结构
pthread_cond_initI()
pthread_cond_destroty
pthread_cond_wait() //线程阻塞函数 pthread_cond_timewait() //阻塞一定时间
pthread_cond_signal() //唤醒条件变量上的线程pthread_cond_broadcast //唤醒所有线程
4.信号量
信号量是用于多线程任务同步的,生产者消费者模型,用于阻塞线程,
一个线程完成某个动作通过信号量告诉别的线程,别的线程再继续别的动作。
指定最大资源数,
多线程共享堆、代码、全局区,独享栈区。线程退出时thread_exit(&t)可以返回一个变量,thread_join(&tid,&t)线程回收可以拿到变量的值,可以把变量放在堆等来进行同步
5.线程最大的缺点?
竞争条件,死锁,高开销,难以调试和维护,可移植性问题
ip/icmp 单播管理协议 IGMP多播管理协议 属于ip协议体系
udp/tcp 传输层协议
对于单播,可以直接指定目标地址和端口发送:
const QString address_text = "127.0.0.1";
const QHostAddress address = QHostAddress(address_text);
const unsigned short port = 12345;
udpSocket->writeDatagram(QNetworkDatagram(send_data,address,port));
对于广播,需要发送到广播地址 "255.255.255.255",即使用 QHostAddress::Broadcast:
udpSocket->writeDatagram(QNetworkDatagram(send_data,QHostAddress::Broadcast,port));
对于组播,需要发送到指定的组播地址,不过要对方加入了这个组播(使用 joinMulticastGroup 和 leaveMulticastGroup 加入/退出组播):
//组播ip必须是D类ip
//D类IP段 224.0.0.0 到 239.255.255.255
//且组播地址不能是224.0.0.1
udpSocket->bind(QHostAddress::AnyIPv4,port); //根据Qt示例,组播的话IPv4和v6分开的
udpSocket->joinMulticastGroup(address); //QHostAddress("224.0.0.2")
udpSocket->writeDatagram(QNetworkDatagram(send_data,address,port)); //QHostAddress("224.0.0.2")
操作完之后,调用相关接口关闭和释放:
-
协程(Coroutine):
- 协程是一种用户态的轻量级线程,也称为协作式多任务。
- 不同于线程,协程的调度是由程序员自己控制的,而不是由操作系统内核进行调度。
- 协程可以在函数内部的某个特定位置暂停执行,并在稍后恢复执行,而不会切换到另一个线程。
- 协程通常不涉及多线程的同步和互斥问题,因此可以避免一些多线程编程中的复杂性。