(一)初识线程与进程

一、前言

    最近项目中用到多线程,问题背景是:有个数据采集设备,使用以太网进行通信,一旦建立以太网链接之后,该设备自己的内置程序就可以并行的循环接收多个类型的数据(也就是它自己有一个数据接收线程),那么现在我需要以一定的周期读取这些数据,并且保证这些数据是该设备最近一次读取的完整数据,因为设备接收并保存的数据是一个比较大的数据区段,它自身是用vector保存的,这就涉及到了对一段内存区域的同时读取操作,即设备自身在不停的写这个内存区域,而我自己的程序在不停的读这个区域,这就需要使用多线程同步技术来保证每次读取的数据都是最新的完整的数据,不能有设备写一半,然后我的程序读一半的情况。这也就是多线程编程中的“生产者——消费者”问题。


二、理解线程与进程

    其实说到线程,自然也要解释什么是进程,说到进程又要联系到程序(即你编辑完成,并能运行的一个具体程序),这三者都有着必然的联系。

    首先说说什么是程序程序是存放在磁盘文件中的可执行目标文件(Windows下是exe文件),想一想是不是?你用IDE新建一个工程,要么是在桌面创建,要么是在D、E、F盘创建,总之它们都是磁盘区域。一个程序本身有生命吗?没有,只有处理器赋予了它生命力时,即你在电脑上(即操作系统)运行它的时候,他才能成为一个活动的实体,我们称这个活动实体为进程,也就是说,进程是一个“执行中的程序”,它是在操作系统上运行的一个程序实体。

    然后再说说什么是线程首先,一个线程是运行在一个进程(即一个程序实体)下面的;其次,一个进程实体下可以有多个线程,线程的本质也是一个函数,只是这个函数可以和进程同步执行;接着,其实进程也是一个线程,这里有两个概念:主线程对等线程每个进程开始生命周期是都是一个单一的线程,它就是主线程,在某一时刻,主线程可以创建一个新的线程,这个线程就是对等线程,对等线程可以有多个(对等线程下面又可以新建它自己的对等线程,这时对等线程就成了主线程);最后主线程和对等线程的唯一区别仅仅在于主线程是该进程中第一个开始运行的线程,对等线程创建并启动后就和主线程在同步的运行,如果没有加入线程控制操作,你无法预测主线程和对等线程的具体执行顺序,记住,同步运行和开始运行是两个不同的概念。

    为了形象的理解线程和进程,博友可以链接这一篇博文,图文并茂,很好理解进程与线程的一个简单解释非常值得链接进去看一看)。


三、进程间切换

   前面已经说过,进程是一个“执行中的程序实体” ,如浏览器是一个进程,QQ也是一个进程,但是你在一台电脑上“同时”运行这个两个进程,即一边聊天,一般浏览网页,完全满足了你的多元化需求啊。但这个“同时”只是看起来的“同时”,因为你在某一时刻还是只能进行聊天或者浏览网页。如果你的电脑配置不是很高,但你同时打开了很多个进程,如QQ、浏览器、视频播放器、音乐播放器、单机游戏、VS2010、QT Creator等,刚刚也讲过,你在同一时刻也只是在某一具体进程上操作,这是其他进程都在睡觉,等待你去操作它们,可能在你只连续操作一个进程的时候(如使用VS2010编辑程序),你不会觉得电脑卡顿,但是突然你接收到你个好朋友的QQ消息,这时你肯定要去点击QQ去查看这个消息,这个时候你的配置不高的电脑就会出现卡顿的现象,可能你点击之后过了半分钟QQ才响应过来(你我想肯定有过,我反正经常有)。

    再总结一下现象:当你打开多个进程(这就是进程并发),如果某一段时间你只操作一个单独的进程,你不会觉得电脑卡,但是当你从你正在工作的进程切换到另一个进程时(如从VS2010切换到QQ),电脑就会出现卡顿的现象,半天反应不过来。这是为什么呢?这是由于不同进程间的切换需要一定的时间消耗造成的。

    既然进程间可以进行切换,也就是说一个进程是间断执行的,进程的间断性,决定了进程具有多种不同的状态,即实质上进程是在这几种不同的状态间进行切换。进程主要有三种状态:就绪状态、运行状态、阻塞状态。

        (1)就绪状态

            当一个进程获得了除处理机以外的一切所需资源,一旦得到处理机即可运行,则称此进程处于就绪状态。就绪进程可以按多个优先级来划分队列。例如,当一个进程由于时间片用完而进入就绪状态时,排入低优先级队列;当进程由I/O操作完成而进入就绪状态时,排入高优先级队列。

        (2)运行状态

            当一个进程在处理机上运行时,则称该进程处于运行状态。处于此状态的进程的数目小于等于处理器的数目,对于单处理机系统,处于运行状态的进程只有一个。在没有其他进程可以执行时(如所有进程都在阻塞状态),通常会自动执行系统的空闲进程。

        (3)阻塞状态

            这里详细说一下进程阻塞状态,进程阻塞就是说这个进程现在暂停了,它或者是在等待某种条件或事件的发生,在条件满足或事件到达之前这进程无法继续执行。进入阻塞状态的进程会暂时放弃CPU资源,处于暂停状态(可以理解为睡眠、等待)。最简单的进程阻塞例子就是,如果你写一个打印字符“A”的程序,程序很简单,如下:

#include <iostream>
#include <string>
using namespace std;
void main()
{
    char a;
    cout << "请从键盘输入字符A: ";
    cin >> a;     //从键盘输入HelloWOrd
    cout << a << endl;
}
你可以试着编辑运行这个程序,出现下面这个界面,提示你输入字符A:


这时,如果你一直不从键盘输入字符“A”,这个程序(进程)就一直停滞在这里,也就是说该进程进入了阻塞状态,但这个进程的阻塞状态不会影响它自己,也不会影响其他的进程,比如你可以接下来去打开QQ进行聊天程序,直到你想起来你的这个打印字符的程序还没有完成,你应该去完成它,然后你用鼠标选中控制台,从键盘输入字符“A”,这个程序就继续运行,打印字符“A”,然后程序运行完毕,进程结束。


    在上面这个例子中,就包含了上述进程的三个状态。具体为,程序编辑完成之后,你点击运行按钮,运行该程序,这个程序就经历了就绪状态和运行状态,这两个状态在这个例子中是连续完成的,只是我们感觉不到,运行之后,然后程序在控制台打印“请从键盘输入字符A:”提示你输入字符,到这里这个进程就进入阻塞状态,然后你去干其他事情(QQ聊天),这个进程就继续阻塞(其实这也是一种就绪状态),接着你在控制台中输入字符“A”,这进程就结束阻塞状态,切换到运行状态,完成整个进程的工作,打印字符“A”。

    最后,简单说说为什么进程间切换会出现电脑卡顿的现象,因为各个进程具有独立的运行环境(即与这个进程运行相关的各种资源),进程间切换的动作需要保存当前进程的信息,恢复下一个运行进程的信息,然后把系统使用权转交给新的运行进程,这个过程是需要一定的时间的,所以会出现电脑卡顿现象。


四、线程状态

    进程具有不同的状态,同样线程也具有不同的状态,总的来说,线程从创建、运行到结束总是处于以下五个状态中,并在其中不停的切换,具体五中状态为:新建状态、就绪状态、运行状态、阻塞状态及死亡状态,各个状态的理解与进程状态类似。

    这里还是详细说一下线程的阻塞状态,本质上来讲,线程的阻塞状态还是和进程的阻塞状态一样理解, 在线程运行过程中,可能由于各种原因进入阻塞状态:
        1>线程通过调用sleep方法进入睡眠状态;
        2>线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
        3>线程试图得到一个锁,而该锁正被其他线程持有;
        4>线程在等待某个触发条件;
        ......           

    也就是说一个线程进入阻塞状态,也是指这个线程本身暂停了,但它还没有结束运行,只是暂时让出CPU资源,这时其他处于就绪状态的线程就可以获得CPU资源,进入运行状态,即一个线程进入阻塞状态不影响其他的对等线程执行。

    线程由于它本身是在一个进程中运行,所以线程间切换比进程间切换需要保存和恢复的信息要少很多,所以线程间切换要比进程间切换快很多。



基于数据挖掘的音乐推荐系统设计实现 需要个代码说明,不需要论文 采用python语言,django框架,mysql数据库开发 编程环境:pycharm,mysql8.0 系统分为前台+后台模式开发 网站前台: 用户注册, 登录 搜索音乐,音乐欣赏(可以在线进行播放) 用户登陆时选择相关感兴趣的音乐风格 音乐收藏 音乐推荐算法:(重点) 本课题需要大量用户行为(如播放记录、收藏列表)、音乐特征(如音频特征、歌曲元数据)等数据 (1)根据用户之间相似性或关联性,给个用户推荐其相似或有关联的其他用户所感兴趣的音乐; (2)根据音乐之间的相似性或关联性,给个用户推荐其感兴趣的音乐相似或有关联的其他音乐。 基于用户的推荐和基于物品的推荐 其中基于用户的推荐是基于用户的相似度找出相似相似用户,然后向目标用户推荐其相似用户喜欢的东西(和你类似的人也喜欢**东西); 而基于物品的推荐是基于物品的相似度找出相似的物品做推荐(喜欢该音乐的人还喜欢了**音乐); 管理员 管理员信息管理 注册用户管理,审核 音乐爬虫(爬虫方式爬取网站音乐数据) 音乐信息管理(上传歌曲MP3,以便前台播放) 音乐收藏管理 用户 用户资料修改 我的音乐收藏 完整前后端源码,部署后可正常运行! 环境说明 开发语言:python后端 python版本:3.7 数据库:mysql 5.7+ 数据库工具:Navicat11+ 开发软件:pycharm
MPU6050是款广泛应用在无人机、机器人和运动设备中的六轴姿态传感器,它集成了三轴陀螺仪和三轴加速度计。这款传感器能够实时监测并提供设备的角速度和线性加速度数据,对于理解物体的动态运动状态至关重要。在Arduino平台上,通过特定的库文件可以方便地MPU6050进行通信,获取并解析传感器数据。 `MPU6050.cpp`和`MPU6050.h`是Arduino库的关键组成部分。`MPU6050.h`是头文件,包含了定义传感器接口和函数声明。它定义了类`MPU6050`,该类包含了初始化传感器、读取数据等方法。例如,`begin()`函数用于设置传感器的工作模式和I2C地址,`getAcceleration()`和`getGyroscope()`则分别用于获取加速度和角速度数据。 在Arduino项目中,首先需要包含`MPU6050.h`头文件,然后创建`MPU6050`对象,并调用`begin()`函数初始化传感器。之后,可以通过循环调用`getAcceleration()`和`getGyroscope()`来不断更新传感器读数。为了处理这些原始数据,通常还需要进行校准和滤波,以消除噪声和漂移。 I2C通信协议是MPU6050Arduino交互的基础,它是种低引脚数的串行通信协议,允许多个设备共享对数据线。Arduino板上的Wire库提供了I2C通信的底层支持,使得用户无需深入了解通信细节,就能方便地MPU6050交互。 MPU6050传感器的数据包括加速度(X、Y、Z轴)和角速度(同样为X、Y、Z轴)。加速度数据可以用来计算物体的静态位置和动态运动,而角速度数据则能反映物体转动的速度。结合这两个数据,可以进步计算出物体的姿态(如角度和角速度变化)。 在嵌入式开发领域,特别是使用STM32微控制器时,也可以找到类似的库来驱动MPU6050。STM32通常具有更强大的处理能力和更多的GPIO口,可以实现更复杂的控制算法。然而,基本的传感器操作流程和数据处理原理Arduino平台相似。 在实际应用中,除了基本的传感器读取,还可能涉及到温度补偿、低功耗模式设置、DMP(数字运动处理器)功能的利用等高级特性。DMP可以帮助处理传感器数据,实现更高级的运动估计,减轻主控制器的计算负担。 MPU6050是个强大的六轴传感器,广泛应用于各种需要实时运动追踪的项目中。通过 Arduino 或 STM32 的库文件,开发者可以轻松地传感器交互,获取并处理数据,实现各种创新应用。博客和其他开源资源是学习和解决问题的重要途径,通过这些资源,开发者可以获得关于MPU6050的详细信息和实践指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值