• 【操作系统】线程


    计算机组成

    计算机核心:CPU,承担了所有任务

    计算机是由cpu+许多寄存器组成,memory是寄存器。在此基础上加上操作系统,在操作系统的基础上运行许多应用程序。

    任务管理器:当前操作系统都运行了哪些应用程序。

    • 应用:正在使用的程序
    • 后台:一般是看不到的,例如flash或者是硬件驱动
    • windows进程:操作系统启动时需要依赖的各种服务

    操作系统:计算机管理者,负责:任务调度、资源分配、统领计算机硬件。程序在操作系统上运行。

    进程

    关系:程序存储在电脑里,操作系统通过执行程序中的文件(exe),操作系统就将程序运行起来了,就变成了操作系统中的各个进程,程序加载至内存,一个程序可以有多个进程。

    进程:进程是一个具有独立功能的程序,在一个数据集上的一次动态执行过程。

    简言之:进程是跑起来的程序。

    进程的性质:

    1. 动态性:进程是程序的一次执行过程,临时的,有生命周期的,动态产生,动态消亡
    2. 并发性:任何进程都可以同其他进程一起并发执行
    3. 独立性:进程是系统进行资源分配和调度的一个独立单位
    4. 结构性:进程由程序、数据集合、进程控制块(PCB)三部分组成

    每个进程都有一个pid号,多个相同程序的多个进程,pid小的是父进程。

    • 进程process:系统分配资源的基本单元
    • 线程thread:cpu调度和执行的基本单元

    为什么引入线程?

    进程间的切换,代价太大,无法满足需求,因此引入线程。

    线程之间相互独立,但是例如内存空间、文件句柄、网络句柄,都是进程中的,是按照进程分配的,因此线程是共享的,线程切换不需要重新分配这些资源。

    线程在任务切换中,是比进程快的,正是由于不需要切换资源。

    为什么要使用线程?

    1. 更快的完成任务
    2. 当一些需要同时操作的场景,例如下载的同时聊天,使其互不影响

    多个线程如何执行的?

    三种执行方式:

    • 串行:按顺序执行
    • 并行:同一时间一起,例如赛跑
    • 并发:单核CPU无法并行,一个CPU在同一时间只能完成一个任务,但是多核就可以

    并发是主要的多线程执行方式。

    操作系统的任务调度采用的方式:时间片轮转的抢占式调用。

    同时:让用户感觉是同时在执行,其实是几个任务切换着去执行,每执行一小部分就更换。

    理论上,多核cpu可以实现并行,但是并发才是主要的执行方式,而且一般都是并发。

    一个CPU同一时间只能执行一个任务,那么个所有要执行的任务,分配一个时间片,例如x秒,那么x秒之后,无论当前任务是否执行完毕,都会开始执行下一个任务。

    并发:相同时间间隔交替执行。

    线程是并发执行的,采用的是时间片轮转的抢占式调用。

    CreateThread函数

    调用函数之后返回线程句柄handle,用来操作线程的。句柄可以理解为id,对应唯一一个标识。

    参数:

    1. 安全描述符:一般是NULL
    2. 栈大小:一般是0,标识默认大小1mb
    3. 线程函数地址:标识函数的功能
    4. 线程函数形参:函数的参数
    5. 创建线程的初始状态:0表示创建后立刻执行,CREATE_SUSPENDED创建后立刻挂起
    6. 线程id:一般是NULL

    关于线程函数:表示线程要做的事情,而形参就是里面的一个单参数。

    线程函数必须是一个参数,如果是多个参数,可以传入结构体。

    最后的线程id,仅用来区分不同线程,而对线程的使用,是句柄的功能。

    1. DWORD WINAPI ThreadProc(LPVOID lpParameter){
    2. int count=(int)lpParameter;
    3. return 0;
    4. }
    5. CreateThread(0,0,&ThreadProc,(void*)80,0,0);

    说明:

    • DWORD表示双字节数据类型,可以理解为unsigned int
    • WINAPI是windows调用约定,仅windows可以用
    • LPVOID和void*是一回事
    • 在函数中必须有形参类型转换

    内核对象

    每次创建线程之后,系统就会在内部为线程分配一个内核对象,即一个thread对应一个内核对象。

    内核对象作用:实现线程管理的函数

    内核对象是什么:操作系统和线程的操作接口,实现了用户和操作系统的交互。

    操作系统只管创建内核对象,但是不管回收,如果不回收,就会内存泄漏。

    操作系统回收内核对象过程

    内置内核对象计数器,初始为0,创建线程+1,系统分配内核对象+1,也就是说,创建完线程之后就直接是2了。

    线程执行完毕-1,手动关闭句柄-1,到此为0,完成了线程回收。

    退出线程两步:

    1. 线程执行结束,有些时候并不能自行结束,需要人工,例如bool的标志位,或者等待或者强制
    2. CloseHandle

    如果在流程中有死循环,先考虑用标志位退出。

    1. if(handle){
    2. isQuit=false;
    3. if(WAIT_TIMEOUT==WaitForSingleObject(handle,100);
    4. TerminateThread(handle,-1);
    5. }
    6. CloseHandle(handle);
    7. handle=0;
    8. }

    首先要温和的退出,然后系统等待时间,如果超时了,就强制退出。

    挂起=暂时不执行。

    SuspendThread(handle);ResumeThread(handle);

    有挂起计数器,挂起一次+1,恢复一次-1,0是最小的,不会再小了。

  • 相关阅读:
    “行泊一体”的火爆与现实困境
    AJAX请求返回流 下载Excel文件
    python的卡夫卡安装教程和使用教程
    在Ubuntu上用sane api实现通用扫描功能
    java_计算内存对象大小
    【笔记】元素水平滑动(松手查看更多、滑动回弹)
    为互连智能合约Connected Contracts使用Axelar SDK
    Docker 镜像
    什么是架构?
    生成 eps 的四种方法(总有一款适合你)
  • 原文地址:https://blog.csdn.net/callmejielun/article/details/126371979