锁+多线程

发布时间 2023-10-14 16:11:57作者: 长大想当太空人

 

互斥锁mutex:保证共享数据操作的完整性,保证在任一时刻只能有一个线程访问对象。锁有两个操作。一个P操作(上锁),一个V操作(解锁)。P和V都是原子操作,就是在执行P和V操作时,不会被插队。锁一般

使用信号量来实现的,mutex其实就是信号量=1。互斥量就是同一时间能够分给一个人,即S=1。S=10表示可以将信号量分给10个人来用。如果一共有20个人那么只能有10个人用,剩下10个人需要等待。

-- 在本项目中有两个操作添加用户和删除用户,信息都是存在消息队列当中,如果不上锁,这两个操作同时执行可能导致在消息队列当中信息错乱。在本项目头文件中加入#include <mutex>引入互斥锁。

unique_lock<mutex> lck(message_queue.m); // 访问共享资源-消息队列,上锁

lck.unlock(); // 访问消息队列结束,解锁

 

条件变量condition_variable:条件变量一般和互斥锁搭配使用,条件变量用于在多线程环境中等待特定事件发生。

-- 在本项目中如果消息队列为空则等待,如果有添加用户和删除用户的操作则将消息队列唤醒。

message_queue.cv.wait(lck) // 队列为空,等待

message_queue.cv.notify_all();  // 出现有添加或删除用户的操作Task操作进队列,唤醒

 

提高程序的并发性:多线程、多进程

多线程消耗少一点,效率差不多

cpu把时间平均分成若干份,系统进行调度,每个线程都要抢时间片,抢到就运行态,否则处于就绪态,线程实际走走停停,看不出

linux下线程本质上是轻量级的进程

内存四区图:

栈区,堆区,数据区,代码区

细分:

 

 进程有自己独立的地址空间

 

如果是进程,就是多个线程共用一个地址空间

在一个地址空间中多个线程共享:代码区,堆区,全局数据区,打开的文件(文件描述符表)都是线程共享的

在一个地址空间中多个线程独享:每个线程都有属于自己的栈区,寄存器(内存中管理的)

 

线程是程序的最小执行单位,进程是操作系统中最小的资源分配单位

(1)每个进程应一个虚拟地址空间,一个进程只能抢一个CPU时间片

(2)一个地址空间中可以划分出多个线程,在有效的资源基础上,能够抢更多的CPU时间片(一个进程里的10个线程都能去抢cpu时间片)

 

CPU的调度和切换:线程的上下文切换比进程快的多

上下文切换:进程/线程分时复用CPU时间片,在切换之前会将上一个任务的状态进行保存,下次切换回这个任务的时候,加载这个状态继续运行

*** 任务从保存到再次加载这个过程就是一次上下文切换