操作系统(第五周 第一二堂总结)

2024-04-16 12:28

本文主要是介绍操作系统(第五周 第一二堂总结),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

回顾

前景知识

概述

定义

进程和线程的关系

进程和线程的区别

线程优缺点 

优点:

缺点:

易混概念

 线程实现方式

线程的类型:

​编辑

多线程模型:

线程函数

头文件:

线程创建函数:

线程退出函数:

进程等待线程函数:

终止线程函数:

线程的使用 

线程基本操作(一)

线程基本操作(二)

并发运行 

总结


回顾

上一篇文章讲了两个点:1、进程的运行 2、进程的通信

其中,进程的运行相对更加重要,进程通信中共享内存法的实现相对更加重要

进程的运行包括:进程的创建、工作、被调度、销毁

1、创建:核心在两个函数:fork()创建子进程;exec()让子进程“脱离”父进程,变为相对独立

2、工作:核心在于理解父子进程的并行

3、被调度:核心在于理解进程的五个状态以及状态之间的转变原因

4、销毁:分为主动销毁以及异常销毁

进程的通信 :共享内存法、消息通信法

1、共享内存法:利用双指针模拟的方式实现进程之间的“消息”通信(本质就是一直用while循环,是一种拟通信)

2、消息通信法:需要内核参与,是一种实质性的进程间消息通信

本篇我们就来讲讲线程

前景知识

多个进程之间是并发运行的,多个线程之间是并行运行的

概述

定义

1、线程是CPU使用的一个基本单元,是程序执行基本单位(不代表进程本身不可以执行程序,这个理解很关键!!)

2、线程是进程中的⼀个执⾏单元,负责当前进程中程序的执⾏

进程和线程的关系

1、一个进程可以有很多个线程,但是一个线程只能属于一个进程

2、线程算是进程上下文的一部分

3、一个程序至少有一个进程

进程和线程的区别

1、线程是程序执行的基本单位,进程是CPU分配资源基本单位

2、进程一定归于操作系统管理,线程不一定

3、进程是程序运行的一个实体,程序运行结束进程将自动被收回;线程是进程运行中的一个执行路径(子序列)

线程优缺点 

优点:

1、多条线程在进程中并发运行,由于线程的切换比进程更快,所以在使用者看来线程比进程更接近于并行状态(本质上仍是并发的)

2、响应性好:既然线程更接近并行状态,那么多条线程并行时,其中一条线程堵塞了,其他线程看起来仍处于运行状态,所以仍会给用户提供服务

3、资源共享:线程之间的资源是共享的(例如代码、数据等),而进程需要通过通信来实现共享

4、经济:由于资源共享,所以创建线程更加经济,并且线程的切换所切换的资源也更少

缺点:

1、 编写多线程程序需要非常仔细的设计。在多线程程序中,因时序上细微的偏差或无意造成的变量共享而引发错误的可能性是很大的。
2、 对多线程程序的调试要比单个线程程序的调试困难得多,因为线程之间的交互难以控制。
3、 将大量计算分为两个部分,并把这个两个部分作为不同的线程来运行的程序在一台单处理器机器上并不一定运行得更快(因为本质上CPU一次仍然只能运行一个线程/一个进程),除非是多处理器真正实现多线程并行执行

易混概念

1、线程和进程在一个处理器中是并发执行的,不是并行运行的

2、线程出现后比进程节省资源的重要原因在于:在一个线程被阻塞后CPU切换其他线程的速度更快

3、进程创建线程后,进程本身也仍然和线程并发执行,共同抢占CPU资源

 线程实现方式

线程的类型:

1、完全由用户创建并管理(用户线程) 

2、完全由内核创建并管理(内核线程)

3、由内核和用户共同管理(组合线程)

多线程模型:

1、多对一模型:多个用户线程映射到一个内核线程

2、一对一模型:一个用户线程映射到一个内核线程

3、多对多模型:多个用户线程映射到多个内核线程

上图中:(a)中就是多对一模型(b)中就是一对一模型 (c)中就是多对多模型 

线程函数

头文件:

#include<pthread.h>

线程创建函数:

int pthread_create(pthread_t* thread,const pthread_attr_t* attr,void* (*start_routine)(void*),void* arg);
  • 作用:创建一个线程
  • 参数:
    • 第一个参数thread是新线程的标识符,后续pthread_*函数通过它来引用新进程。其类型的pthread_t定义为:
    • 第二个参数attr用于设置新线程的属性。传递NULL表示使用默认线程属性
    • 第三个参数是返回值、参数变量都为void*的函数指针
    • 第四个参数arg表示新线程的参数

线程退出函数:

        线程函数在结束时最好调用如下函数,该函数通过retval参数向进程的回收者传递其退出信息

void pthread_exit(void* retval);

进程等待线程函数:

int pthread_join(pthread_t thread,void**retval);

作用:阻塞进程直到其所有线程运行结束,再开始执行进程
参数:
        thread是目标现成的标识符
        retval是目标线程返回的退出信息
        返回值:成功0,失败返回错误码

终止线程函数:

int pthread_cannel(pthread_t thread);

作用:终止一个线程,即取消线程
参数:
        thread是目标线程标识符
        返回值:成功0,失败返回错误码

线程的使用 

线程基本操作(一)

#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>void* fun(void* arg)
{for(int i=0;i<5;i++){printf("fun run\n");sleep(1);}
}int main()
{pthread_t id;pthread_create(&id,NULL,fun,NULL);for(int i=0;i<2;i++){printf("main run\n");sleep(2);}exit(0);
}

执行结果: 

关键点:

1、进程和线程并发运行,抢占CPU资源

2、进程运行结束后,其线程也会被强制结束

3、线程创建需要一定的时间

线程基本操作(二)

#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>void* fun(void* arg)
{for(int i=0;i<5;i++){printf("fun run\n");sleep(1);}pthread_exit("fun over\n");//结束时会发送信息给进程
}int main()
{pthread_t id;//存储线程的idpthread_create(&id,NULL,fun,NULL);for(int i=0;i<2;i++){printf("main run\n");sleep(1);}char* s=NULL;pthread_join(id,(void**)&s);//阻塞进程等待线程结束,并得到线程的结束信息printf("s=%s",s);exit(0);
}

执行结果:

关键点: 

1、利用pthread_join来阻塞进程

2、利用pthread_exit来实现进程和线程的通信(消息传递)

并发运行 

#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>void* fun(void* arg)
{int index=*(int*)arg;for(int i=0;i<3;i++){printf("index=%d\n",index);sleep(1);}}int main()
{pthread_t id[5];int i;for(i=0;i<5;i++){index[i]=i;pthread_create(&id[i],NULL,fun,(void*)&index[i]);//进程先运行结束后,等待线程运行}	for(i=0;i<5;i++){pthread_join(id[i],NULL);//等待五个线程}exit(0);
}

执行结果 :

关键点:

1、不同线程并发运行

2、线程创建需要时间,按照现在的CPU速度,进程早已走完了5个循环 

总结

本文到这里就结束啦~~这堂课的内容较为杂乱、复杂,但是学一学拓展一下知识是非常好的呀~~
如果觉得对你有帮助,辛苦友友点个赞哦~

知识来源:操作系统概念(黑宝书)、山东大学高晓程老师PPT及课上讲解。不要私下外传

这篇关于操作系统(第五周 第一二堂总结)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/908792

相关文章

Python中logging模块用法示例总结

《Python中logging模块用法示例总结》在Python中logging模块是一个强大的日志记录工具,它允许用户将程序运行期间产生的日志信息输出到控制台或者写入到文件中,:本文主要介绍Pyt... 目录前言一. 基本使用1. 五种日志等级2.  设置报告等级3. 自定义格式4. C语言风格的格式化方法

Spring 依赖注入与循环依赖总结

《Spring依赖注入与循环依赖总结》这篇文章给大家介绍Spring依赖注入与循环依赖总结篇,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. Spring 三级缓存解决循环依赖1. 创建UserService原始对象2. 将原始对象包装成工

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

在Java中实现线程之间的数据共享的几种方式总结

《在Java中实现线程之间的数据共享的几种方式总结》在Java中实现线程间数据共享是并发编程的核心需求,但需要谨慎处理同步问题以避免竞态条件,本文通过代码示例给大家介绍了几种主要实现方式及其最佳实践,... 目录1. 共享变量与同步机制2. 轻量级通信机制3. 线程安全容器4. 线程局部变量(ThreadL

Spring Boot 与微服务入门实战详细总结

《SpringBoot与微服务入门实战详细总结》本文讲解SpringBoot框架的核心特性如快速构建、自动配置、零XML与微服务架构的定义、演进及优缺点,涵盖开发环境准备和HelloWorld实战... 目录一、Spring Boot 核心概述二、微服务架构详解1. 微服务的定义与演进2. 微服务的优缺点三

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

JavaSE正则表达式用法总结大全

《JavaSE正则表达式用法总结大全》正则表达式就是由一些特定的字符组成,代表的是一个规则,:本文主要介绍JavaSE正则表达式用法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录常用的正则表达式匹配符正则表China编程达式常用的类Pattern类Matcher类PatternSynta

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

Nginx Location映射规则总结归纳与最佳实践

《NginxLocation映射规则总结归纳与最佳实践》Nginx的location指令是配置请求路由的核心机制,其匹配规则直接影响请求的处理流程,下面给大家介绍NginxLocation映射规则... 目录一、Location匹配规则与优先级1. 匹配模式2. 优先级顺序3. 匹配示例二、Proxy_pa

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio