当前课程知识点:操作系统 >  第十七讲 同步互斥 >  17.4 基于软件的同步方法 >  17.4 基于软件的同步方法

返回《操作系统》慕课在线视频课程列表

17.4 基于软件的同步方法在线视频

17.4 基于软件的同步方法

下一节:17.5 高级抽象的同步方法

返回《操作系统》慕课在线视频列表

17.4 基于软件的同步方法课程教案、知识点、字幕

下面我们来介绍软件同步方法

基于软件的同步方法呢

它是在两个进程之间

通过共享变量的访问

来实现线程之间的同步

那这一类方法呢

我们给它的大致模式先给它描述

假定有两个线程 T0和T1

然后每一个线程呢

它的实现代码都是这样一种格局

进入区 临界区 退出区

然后我们在这里控制的地方呢

是在进入区和退出区里头

通过一些共享变量的修改

来同步它们之间的行为

那我们在这里的所有的方法呢

都是要讨论在进入区里头

我要对哪些共享的变量

进行什么样的设置和判断

那这些方法呢跟我们前面讨论到的

生活当中同步问题呢是一致的

我们跟那儿呢做一个类比性的讨论

首先第一个尝试 说

我在这里呢

在两个线程之间共享一个变量

这个变量呢表示允许谁进入临界区

那这里是允许进入

临界区的线程的ID

好 那这时候我们说

线程Ti实现代码呢是这样的

它先判断当前这个turn的值

到底是不是i

如果不是 也就相当于我本身是i

允许另外一个线程进入临界区

i不允许进入临界区

那这时候呢它就一直等待

等待另一个线程把它改成i

好 如果 这样的话就是

在它自己等待它变成是它之后

它能进去 进去之后呢

执行临界区的代码

执行完毕之后退出的时候呢

在退出区呢 它把turn改成j

也就说另一个线程ID

那我们看这种情况

能满足我们的要求吗

如果说turn的值是i

那么这时候呢线程Ti

进入一个判断是可以的

OK 它就进去了

好 如果不是那就它一直等着

那这时候说如果这个地方

是j来访问那它就进不去

那这时候我们看到

i和j之间访问临界区的

关系是啥样的

开始的时候假定它等于i

那么这时候呢i能进去

j能进去吗 j进不去

好 i进去之后它改成j

好 这时候如果i再来进的话

它进不去了 j也能进去

这时候我们就会发现一种现象

它们俩是交替进入临界区

这是很好的一种做法

但如果说某一个线程

想连续两次进入临界区

那这时候它就会有麻烦

所以这种做法呢

它能够满足我们说的忙则等待

也就说我在这里头

任何一个线程进到里头去的时候

不会有第二个同时在里头

但是它不满足空闲则入

也就相当于如果说这里是空闲的

但是这时候编号不是你

那你进不去了

好 那我们对这种做法呢

进行进一步的修改

那这是第二种做法

我们在前面呢

设置一个变量turn不够用

那我们这儿呢现在设置两个变量

也就相当于一个数组

描述每个线程它是否是在临界区

这种做法和刚才那个地方

有什么不一样呢

这就相当于我是用两个来表示

我尝试着解决两个线程

需要交替进入的问题

好 那这时候呢

线程Ti的实现代码我们这样来做

先判断另外一个线程它的flag是1

如果它不是

也就相当于它没在临界区里头

那我就把自己的标识改成1

那这时候我在临界区

然后进入临界区

出来的时候

我把自己这个标识呢改成0

那这种做法呢

和我们前面的第一种尝试

想想看有什么区别

线程Ti想进入临界区

它做判断

假设另一个没有在临界区

那它判断是通过的

OK 好 它这时候呢

把自己的标识改了然后进去

如果它再来一遍可以吗

它再来一遍同样的做法仍然没问题

一个线程连续进入是可以的

好 如果说它交替进入呢

那也没问题

好像改善了我们前面

第一种尝试里头的麻烦

但是它有什么问题吗

还记得我们在前面讲

采购当中那个同步

说两个先判断 后设置

两个同时判断之后会出现什么

同时设置

那同时设置之后呢

两个线程就同时进入到

临界区里头去了

那这时候这是它的毛病

它就不能满足忙则等待

好 那这种做法不行了

之后怎么办呢

我们把前面含义做一下改动

也就说前面我们就像

我们在采购那个同步里头

我们是先贴标签还是后贴标签

刚才那种做法呢

相当于是后贴标签

那这时候呢我把这个flag含义改了

不表示我在临界区

而表示我想进入临界区

那这时候呢相当于我是先贴标签

这是它的实现代码

先贴标签后做判断

这时候我们说 前面的采购同步里头

先贴标签后做判断会出现什么问题

两个都有可能判断完了之后

都觉得自己进不去

OK 那就都进不去了

那这是它的问题

它能够满足不能同时进

但是不能满足如果空闲我可以进去

这就是空闲则入

好 这种做法呢也不行

也就相当于我把标签贴在前头

贴在后头都不行

好 那这时候呢

我把这两个合在一起

这就是我们这里的Peterson算法

这是两个进程之间

能够完成同步的算法

它怎么做的呢

turn表示当前谁进入临界区

而flag表示我请求进入临界区

好 这时候我们说

进入区的代码是先设置标志

相当于这时候设置的标志有两个

一个是我想进入

第二个是turn的值

然后我在后面做一个判断

那这时候想想看

这和我们前面先设置标志

后做判断有什么区别

那这地方它俩同时

设置了一个变量 turn

这是问题的关键

我把这一步设置完了之后呢

我后面的判断

就能够区别出来它们俩

好 我们具体看一下

如果说另一个线程j

它没有申请进入

那我这儿直接能进去没问题

因为这两个条件里头

有一个不成立它就进来了

好 假定说另一个也申请了

它也变成true

好 那这时候会什么呢

会有这样一个turn在这儿等着

因为这个变量是

往存储单元里写数据

两个线程同时往里写

或者并发往里写

那总是有一前一后

好 不管是哪一个

因为在总线上仲裁之后

我是有一前一后的

在这里呢

假定我在这儿

我写的是j

如果我是最后一个写的

会什么样的情况

另一个flag是true

然后我的标志呢

turn的标志是按我最后写的

那我判断相当于

如果两个同时想进入的话

后设置turn这个标志的

那这个条件就成立

而先写的后面这个条件不成立

好 那这样的话

就是先写turn这个标志的能进去

而后写的就会在这儿等着

那等到在退出区里头我把flag改了

好 那么这个条件呢

前面这个就不成立了

好 那这是后写标志turn

也就能进去了

好 那这一个呢

我们说跟我们前面讲

采购同步一样的

把它们所有的情况

罗列出来进行分析

写标志 判断它们

所有可能的顺序一一进行分析

我们说Peterson算法呢

是可以完成

我们的两个进程之间同步

好 那在这种情况下我们说

要是更多的进程怎么办

我们先把这个两个进程的做法呢

换一种形式来写

这就是Dekkers算法

它的做法是什么呢

跟标志 跟我们前面的几乎一样的

但是这个进入区的判断呢

相对来说复杂一些

那实际上也是先写

然后后面去判断

判断完了之后

那看如果另一个也想进入

实际上它就把自己改为false

然后开始等待 前面这个

这种做法呢

退出去的做法跟那儿是一样的

这种做法呢

它可以很方便的扩展到多个线程

而扩展到多个线程的做法呢

就是我们这个图呢给出的图示

我在这里有一个turn这个变量

这是共享的

然后是每一个线程 若干个

我把它排成一个环

每一个里头有一个flag的标志

好 那我在进入的时候呢

我先填这个flag标志说我想进入

然后去看turn标志

如果有多个想写

那这个时候呢它总是会有最后一个

好 那么在这种情况下

这是当前正在访问临界区的那一个线程

好 我要做什么呢

进入区我就从这儿往后一直到i

这是个环

也可能会在另外一个位置

就从它起头 到i这个地方

这一段里是不是有其它线程

也跟我一样的 同时想进入

如果有 让他们先访问

访问完了之后

这个turn会一直往后蹿

蹿到我这儿

那这时候我进去

那这就是我们这里说的

进入区的做法

而退出区等我用完了之后

后面有可能

也有其他在等着的

我顺序的把标志

给到下一个想进入的

如果都没有转一圈之后

我把自己留这儿就行了

好 这是N个进程的软件同步方法

好 那我们看到

这几种方法搁到一起之后

我们发现这个

基于软件的同步方法它很复杂

两个进程之间需要多个共享数据项

我才能够完成这个同步

同时这是一个盲等待

也就说我在进入区里头

我必须频繁地来

查询共享变量的状态

那这是呢软件同步方法

所面临的问题

好 经过这几个算法的介绍呢

我们知道通过软件方法

是可以实现多个进程之间的同步的

但是这个方法比较复杂

里头有错之后也不好查找

如果说你是多个线程

多个临界区

那么这时候这个问题会变得更复杂

操作系统课程列表:

第零讲 在线教学环境准备

-0.1 Piazza讨论区

--piazza访问和使用

--html

-0.2 在线实验平台

--实验平台使用帮助

--平台使用帮助

--Gitlab使用帮助

--IBM内部账号初始化

-0.2在线实验平台

--Raw HTML

第一讲 操作系统概述

-1.1 课程概述

--视频

-第一讲 操作系统概述--练习

-1.2 教学安排

--视频

-1.3 什么是操作系统

--Video

-1.4 为什么学习操作系统,如何学习操作系统

--Video

-1.5 操作系统实例

--视频

-1.6 操作系统的演变

--视频

-1.7 操作系统结构

--视频

第二讲 实验零 操作系统实验环境准备

-2.1 前言和国内外现状

--2.1 前言和国内外现状

-2.2 OS实验目标

--2.2 OS实验目标

-2.3 8个OS实验概述

--2.3 8个OS实验概述

-2.4 实验环境搭建

--2.4 实验环境搭建

-2.5 x86-32硬件介绍

--2.5 x86-32硬件介绍

-2.6 ucore部分编程技巧

--2.6 ucore部分编程技巧

-2.7 演示实验操作过程

--2.7 演示实验操作过程

--Q6

--Q7

--Q10

第三讲 启动、中断、异常和系统调用

-3.1 BIOS

--3.1 BIOS

-3.2 系统启动流程

--3.2 系统启动流程

-3.3 中断、异常和系统调用比较

--3.3 中断、异常和系统调用比较

-第三讲 启动、中断、异常和系统调用--3.3 中断、异常和系统调用比较

-3.4 系统调用

--3.4 系统调用

-第三讲 启动、中断、异常和系统调用--3.4 系统调用

-3.5 系统调用示例

--3.5 系统调用示例

-3.6 ucore+系统调用代码

--3.6 ucore+系统调用代码

第四讲 实验一 bootloader启动ucore os

-4.1 启动顺序

--4.1 启动顺序

-4.2 C函数调用的实现

--4.2 C函数调用的实现

-4.3 GCC内联汇编

--4.3 GCC内联汇编

-4.4 x86中断处理过程

--4.4 x86中断处理过程

-4.5 练习一

--4.5 练习一

-4.6 练习二

--4.6 练习二

-4.7 练习三

--4.7 练习三

-4.8 练习四 练习五

--4.8 练习四练习五

-4.9 练习六

--4.9 练习六

第五讲 物理内存管理: 连续内存分配

-5.1 计算机体系结构和内存层次

--5.1 计算机体系结构和内存层次

-5.2 地址空间和地址生成

--5.2 地址空间和地址生成

-5.3 连续内存分配

--5.3 连续内存分配

-5.4 碎片整理

--5.4 碎片整理

-5.5 伙伴系统

--5.5 伙伴系统

-第五讲 物理内存管理: 连续内存分配--5.6 练习

第六讲 物理内存管理: 非连续内存分配

-6.1 非连续内存分配的需求背景

--6.1 非连续内存分配的需求背景

-6.2 段式存储管理

-- 6.2 段式存储管理

-6.3 页式存储管理

--6.3 页式存储管理

-6.4 页表概述

--6.4 页表概述

-6.5 快表和多级页表

--6.5 快表和多级页表

-6.6 反置页表

--6.6 反置页表

-6.7 段页式存储管理

--6.7 段页式存储管理

-第六讲 物理内存管理: 非连续内存分配--6.8 练习

第七讲 实验二 物理内存管理

-7.1 了解x86保护模式中的特权级

--7.1 了解x86保护模式中的特权级

-第七讲 实验二 物理内存管理--7.1 了解x86保护模式中的特权级

-7.2 了解特权级切换过程

--7.2 了解特权级切换过程

-第七讲 实验二 物理内存管理--7.2 了解特权级切换过程

-7.3 了解段/页表

--7.3 了解段/页表

-第七讲 实验二 物理内存管理--7.3 了解段/页表

-7.4 了解UCORE建立段/页表

--7.4 了解ucore建立段/页表

-第七讲 实验二 物理内存管理--7.4 了解UCORE建立段/页表

-7.5 演示lab2实验环节

--7.5 演示lab2实验环节

第八讲 虚拟存储概念

-8.1 虚拟存储的需求背景

--8.1 虚拟存储的需求背景

-8.2 覆盖和交换

--8.2 覆盖和交换

-8.3 局部性原理

--8.3 局部性原理

-8.4 虚拟存储概念

--8.4 虚拟存储概念

-8.5 虚拟页式存储

--8.5 虚拟页式存储

-8.6 缺页异常

--8.6 缺页异常

第九讲 页面置换算法

-9.1 页面置换算法的概念

--9.1 页面置换算法的概念

-9.2 最优算法、先进先出算法和最近最久未使用算法

--9.2 最优算法、先进先出算法和最近最久未使用算法

-第九讲 页面置换算法--9.2 最优算法、先进先出算法和最近最久未使用算法

-9.3 时钟置换算法和最不常用算法

--9.3 时钟置换算法和最不常用算法

-第九讲 页面置换算法--9.3 时钟置换算法和最不常用算法

-9.4 Belady现象和局部置换算法比较

--9.4 Belady现象和局部置换算法比较

-第九讲 页面置换算法--9.4 Belady现象和局部置换算法比较

-9.5 工作集置换算法

--9.5 工作集置换算法

-第九讲 页面置换算法--9.5 工作集置换算法

-9.6 缺页率置换算法

--9.6 缺页率置换算法

-第九讲 页面置换算法--9.6 缺页率置换算法

-9.7 抖动和负载控制

--9.7 抖动和负载控制

第十讲 实验三 虚拟内存管理

-10.1 实验目标:虚存管理

--10.1 实验目标:虚存管理

-第十讲 实验三 虚拟内存管理--10.1 实验目标:虚存管理

-10.2 回顾历史和了解当下

-- 10.2 回顾历史和了解当下

-第十讲 实验三 虚拟内存管理--10.2 回顾历史和了解当下

-10.3 处理流程、关键数据结构和功能

--10.3 处理流程、关键数据结构和功能

-第十讲 实验三 虚拟内存管理--10.3 处理流程、关键数据结构和功能

-10.4 页访问异常

--10.4 页访问异常

-第十讲 实验三 虚拟内存管理--10.4 页访问异常

-10.5 页换入换出机制

--10.5 页换入换出机制

-第十讲 实验三 虚拟内存管理--10.5 页换入换出机制

第十一讲 进程和线程

-11.1 进程的概念

--11.1 进程的概念

-第十一讲 进程和线程--11.1 进程的概念

-11.2 进程控制块

--11.2 进程控制块

-第十一讲 进程和线程--11.2 进程控制块

-11.3 进程状态

--11.3 进程状态

-第十一讲 进程和线程--11.3 进程状态

-11.4 三状态进程模型

--11.4 三状态进程模型

-11.5 挂起进程模型

--11.5 挂起进程模型

-第十一讲 进程和线程--11.5 挂起进程模型

-11.6 线程的概念

--11.6 线程的概念

-第十一讲 进程和线程--11.6 线程的概念

-11.7 用户线程

--11.7 用户线程

-第十一讲 进程和线程--11.7 用户线程

-11.8 内核线程

--11.8 内核线程

-第十一讲 进程和线程--11.8 内核线程

第十二讲 进程控制

-12.1 进程切换

--12.1 进程切换

-第十二讲 进程控制--12.1 进程切换

-12.2 进程创建

--12.2 进程创建

-第十二讲 进程控制--12.2 进程创建

-12.3 进程加载

--12.3 进程加载

-第十二讲 进程控制--12.3 进程加载

-12.4 进程等待与退出

--12.4 进程等待与退出

-第十二讲 进程控制--12.4 进程等待与退出

第十三讲 实验四 内核线程管理

-13.1 总体介绍

--13.1 总体介绍

-13.2 关键数据结构

--13.2 关键数据结构

-13.3 执行流程

--13.3 执行流程

-13.4 实际操作

--13.4 实际操作

第十四讲 实验五 用户进程管理

-14.1 总体介绍

--14.1 总体介绍

-14.2 进程的内存布局

--14.2 进程的内存布局

-14.3 执行ELF格式的二进制代码-do_execve的实现

--14.3 执行ELF格式的二进制代码-do_execve的实现

-14.4 执行ELF格式的二进制代码-load_icode的实现

--14.4 执行ELF格式的二进制代码-load_icode的实现

-14.5 进程复制

--14.5 进程复制

-14.6 内存管理的copy-on-write机制

--14.6 内存管理的copy-on-write机制

第十五讲 处理机调度

-15.1 处理机调度概念

--15.1 处理机调度概念

-第十五讲 处理机调度--15.1 处理机调度概念

-15.2 调度准则

--15.2 调度准则

-15.3 先来先服务、短进程优先和最高响应比优先调度算法

--15.3 先来先服务、短进程优先和最高响应比优先调度算法

-第十五讲 处理机调度--15.3 先来先服务、短进程优先和最高响应比优先调度算法

-15.4 时间片轮转、多级反馈队列、公平共享调度算法和ucore调度框架

--15.4 时间片轮转、多级反馈队列、公平共享调度算法和ucore调度框架

-第十五讲 处理机调度--15.4 时间片轮转、多级反馈队列、公平共享调度算法和uc

-15.5 实时调度和多处理器调度

--15.5 实时调度和多处理器调度

-第十五讲 处理机调度--15.5 实时调度和多处理器调度

-15.6 优先级反置

--15.6 优先级反置

-第十五讲 处理机调度--15.6 优先级反置

第十六讲 实验六 调度器

-16.1 总体介绍和调度过程

--16.1 总体介绍和调度过程

-16.2 调度算法支撑框架

--16.2 调度算法支撑框架

-16.3 时间片轮转调度算法

--16.3 时间片轮转调度算法

-16.4 Stride调度算法

--16.4 Stride调度算法

第十七讲 同步互斥

-17.1 背景

--17.1 背景

-17.2 现实生活中的同步问题

--17.2 现实生活中的同步问题

-第十七讲 同步互斥--17.2 现实生活中的同步问题

-17.3 临界区和禁用硬件中断同步方法

--17.3 临界区和禁用硬件中断同步方法

-第十七讲 同步互斥--17.3 临界区和禁用硬件中断同步方法

-17.4 基于软件的同步方法

--17.4 基于软件的同步方法

-第十七讲 同步互斥--17.4 基于软件的同步方法

-17.5 高级抽象的同步方法

--17.5 高级抽象的同步方法

-第十七讲 同步互斥--17.5 高级抽象的同步方法

第十八讲 信号量与管程

-18.1 信号量

--18.1 信号量

-第十八讲 信号量与管程--18.1 信号量

-18.2 信号量使用

--18.2 信号量使用

-第十八讲 信号量与管程--18.2 信号量使用

-18.3 管程

--18.3 管程

-第十八讲 信号量与管程--18.3 管程

-18.4 哲学家就餐问题

--18.4 哲学家就餐问题

-18.5 读者-写者问题

--18.5 读者-写者问题

第十九讲 实验七 同步互斥

-19.1 总体介绍

--19.1 总体介绍

-19.2 底层支撑

--19.2 底层支撑

-第十九讲 实验七 同步互斥--19.2 底层支撑

-19.3 信号量设计实现

--19.3 信号量设计实现

-第十九讲 实验七 同步互斥--19.3 信号量设计实现

-19.4 管程和条件变量设计实现

--19.4 管程和条件变量设计实现

-第十九讲 实验七 同步互斥--19.4 管程和条件变量设计实现

-19.5 哲学家就餐问题

--19.5 哲学家就餐问题

第二十讲 死锁和进程通信

-20.1 死锁概念

--20.1 死锁概念

-第二十讲 死锁和进程通信--20.1 死锁概念

-20.2 死锁处理方法

--20.2 死锁处理方法

-第二十讲 死锁和进程通信--20.2 死锁处理方法

-20.3 银行家算法

--20.3 银行家算法

-第二十讲 死锁和进程通信--20.3 银行家算法

-20.4 死锁检测

--20.4 死锁检测

-第二十讲 死锁和进程通信--20.4 死锁检测

-20.5 进程通信概念

--20.5 进程通信概念

-第二十讲 死锁和进程通信--20.5 进程通信概念

-20.6 信号和管道

--20.6 信号和管道

-第二十讲 死锁和进程通信--20.6 信号和管道

-20.7 消息队列和共享内存

--20.7 消息队列和共享内存

-第二十讲 死锁和进程通信--20.7 消息队列和共享内存

第二十一讲 文件系统

-21.1 文件系统和文件

--21.1 文件系统和文件

-第二十一讲 文件系统--21.1 文件系统和文件

-21.2 文件描述符

--21.2 文件描述符

-第二十一讲 文件系统--21.2 文件描述符

-21.3 目录、文件别名和文件系统种类

--21.3 目录、文件别名和文件系统种类

-第二十一讲 文件系统--21.3 目录、文件别名和文件系统种类

-21.4 虚拟文件系统

--21.4 虚拟文件系统

-第二十一讲 文件系统--21.4 虚拟文件系统

-21.5 文件缓存和打开文件

--21.5 文件缓存和打开文件

-第二十一讲 文件系统--21.5 文件缓存和打开文件

-21.6 文件分配

--21.6 文件分配

-第二十一讲 文件系统--21.6 文件分配

-21.7 空闲空间管理和冗余磁盘阵列RAID

--21.7 空闲空间管理和冗余磁盘阵列RAID

-第二十一讲 文件系统--21.7 空闲空间管理和冗余磁盘阵列RAID

第二十二讲 实验八 文件系统

-22.1 总体介绍

--22.1 总体介绍

-第二十二讲 实验八 文件系统--22.1 总体介绍

-22.2 ucore 文件系统架构

--22.2 ucore 文件系统架构

-第二十二讲 实验八 文件系统--22.2 ucore 文件系统架构

-22.3 Simple File System分析

--22.3 Simple File System分析

-第二十二讲 实验八 文件系统--22.3 Simple File System分析

-22.4 Virtual File System分析

--22.4 Virtual File System分析

-第二十二讲 实验八 文件系统--22.4 Virtual File System分

-22.5 I/O设备接口分析

--22.5 I/O设备接口分析

-第二十二讲 实验八 文件系统--22.5 I/O设备接口分析

-22.6 执行流程分析

--22.6 执行流程分析

第二十三讲 I/O子系统

-23.1 I/O特点

--视频

-第二十三讲 I/O子系统--23.1 I/O特点

-23.2 I/O结构

--816C80A0F5E3B8809C33DC5901307461

-第二十三讲 I/O子系统--23.2 I/O结构

-23.3 I/O数据传输

--C58221E14388B9DB9C33DC5901307461

-第二十三讲 I/O子系统--23.3 I/O数据传输

-23.4 磁盘调度

--567A3F1FCBFB3F4C9C33DC5901307461

-第二十三讲 I/O子系统--23.4 磁盘调度

-23.5 磁盘缓存

--C327536B80D25CE79C33DC5901307461

-第二十三讲 I/O子系统--23.5 磁盘缓存

html

-html

--html

17.4 基于软件的同步方法笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。