临界区

线程同步和互斥

百般思念 提交于 2020-04-01 09:45:17
异步:好比赛跑,各跑各的,互不打扰 同步:好比接力赛,必须接棒后才能跑 互斥:好比独木桥,一次只能过一个 WIN32中的同步机制主要有: 1).临界区(Critical section) 2).信号量(semaphore) 3).互斥量(mutex) 4).事件(Event) 用户模式下:原子操作,临界区,通过对多线程的串行化的操作来访问公共资源或一段代码,速度快,适合控制数据访问。 内核模式下:1.互斥量:为协调共同对一个共享资源的单独访问而设计。 2.信号量:为控制一个具有有限数量用户资源而单独设计。 3.事件:用来通知线程有一些事件已经发生,从而启动后继任务的开始。 来源: https://www.cnblogs.com/liu6666/p/12610415.html

多线程中volatile关键字的作用

随声附和 提交于 2020-03-30 12:49:08
原文链接: https://blog.csdn.net/xuwentao37x/article/details/27804169 多线程的程序是出了名的难编写、难验证、难调试、难维护,这通常是件苦差事。不正确的多线程程序可能可以运行很多年也不出一点错,直到满足某些临界的条件时,才出现意想不到的奇怪错误。 不用说,编写多线程程序的程序员需要使用可能得到的所有帮助。这期专栏将专注于讨论竞争条件(race conditions)——这通常是多线程程序中各种麻烦的根源——深入了解它并提供一些工具来防止竞争。令人惊异的是,我们将让编译器尽其所能来帮助你做这些事。 仅仅一个不起眼的关键字。 尽管C和C++标准对于线程都明显的“保持沉默”,但它们以volatile关键字的形式,确实为多线程保留了一点特权。 就象大家更熟悉的const一样,volatile是一个类型修饰符(type modifier) 。它是被设计用来修饰被不同线程访问和修改的变量。如果没有volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。下面我们来一个个说明。 考虑下面的代码: 代码: class Gadget { public: void Wait() { while (!flag_) { Sleep(1000); // sleeps for 1000 milliseconds }

线程、进程间通信

我的梦境 提交于 2020-03-22 18:17:06
线程 在无线程的系统中,进程是: 存储器、外设等资源的分配单位 处理机调度的对象 在引入线程后: 线程 是 处理机调度 的对象 进程 作为 资源分配 单位 同一进程内可包含 多个线程 ,他们 共享进程的资源 线程的使用 引入线程的原因: 并行实体 共享同一个地址空间和所有可用数据 的能力 比进程更容易创建、撤销 性能的提高。如果存在着大量的计算和大量的IO处理,多线程允许这些活动 彼此重叠进行 ,加快应用程序执行的速度 多处理机系统,多线程可以真正地并行 例子:文字处理软件 如果程序只有一个线程,那么只要已启动磁盘备份,键盘和鼠标输入的命令都会不予理睬,知道备份结束,用户将感觉到程序反应迟钝 使用三个线程: 一个线程和用户交互 第二个线程在后台重新进行格式处理 第三个线程处理磁盘备份 例子:万维网服务器 Web服务器:接受用户请求,将所请求的页面发回给客户机 多线程实现: 一个线程(分配程序)从网络中读入工作请求,检查请求后,提交给一个工作线程(唤醒睡眠的工作线程) while (true) { get_next_request(&buf); handoff_work(&buf); } 工作线程负责调入页面(读高度缓存或磁盘) while (true) { wait_for_work(&buf); look_for_page_in_cache(&buf, &page); if

2019年9月25日星期三(STM32 ucos3)

99封情书 提交于 2020-03-17 17:12:09
一.UCOS 1.概念 uc/OS-III(Micro C OS Thee),微型C语言编写的操作系统第三版。是一个可升级,可固化,多任务基于优先级的可抢占式实时内核。 ucos的任务个数不限制,实现了操作系统所需求的大部分功能,资源管理,同步,任务之间的通信。除了这些基本的功能以外,还提供一些其他的实时性内核找不到的特色功能,比如完备的运行时间测量,也可以直接发送信号/消息到某个任务,任务也可以同时等待多个内核对象 由于ucos体积微小,功能强悍,可移植性强,在微控制器领域应用广泛 ucos要收费,有时候我们会选择免费的系统,比如freeRTOS....,以及一些其他和物联网结合操作系统(华为liteOS 阿里巴巴.. 腾讯..) 2.ucos移植 (1)源代码结构 EvalBoards ------------ 工程文件 uc-CPU -------------- CPU相关代码 uc-LIB -------------- 和硬件/编译器 无关的库函数(字符串 数学 内存) uCOS-III ----------- ucos操作系统相关代码 (2)将源码拷贝到工程,修改源码(详情见手册) (3)特性 3.ucos的任务调度和任务 合作式调度 -------- 多个任务按照指定时间和顺序依次运行,下一个任务等待上一个任务时间用完再开始运行 抢占式调度 --------

操作系统7-信号量与管程

旧街凉风 提交于 2020-03-17 15:31:59
回顾一下 : 并发问题:多线程并发导致资源竞争 同步概念: ---------1. 协调多线程对 共享数据 的访问 ---------2.任何时刻只能由一个线程执行临界区代码 确保同步正确的方法 ---------底层硬件支持 ---------高层次的编程抽象( 锁 ) 信号量是锁机制在同一层上的高层抽象编程方法 一、 信号量semaphore 信号量是操作系统提供的一种 协调共享资源访问 的方法, 用信号量表示系统资源的数量 信号是一种抽象数据类型,由一个整型(sem)变量和两个原子操作组成: 1)P():sem减1,如sem<0,表示申请资源(减1)后没有资源了,需要等待 2)V():sem加1,如sem<=0,即一个资源用完(加1)但还是小于0表示还有资源在等待,那么就唤醒一个等待进程 信号量是被保护的整数变量。初始化完成后就只能通过P()和V()操作来修改,并且由操作系统来保证PV操作时原子操作 P可能由于没有资源而进入阻塞状态,但是V操作不会被阻塞 假定信号量实现的同步是公平的,线程不会被阻塞在P()操作中,并且信号量等待按先进先出 信号量的实现 class Semophore { int sem ; WaitQueue q ; } Semophore :: P ( ) { sem -- ; //申请一个资源 if ( sem < 0 ) //资源不够,要等待 {

临界区和C++使用方式

霸气de小男生 提交于 2020-03-17 04:05:52
一.临界资源 临界资源是一次仅允许一个进程使用的共享资源。 各进程采取互斥的方式,实现共享的资源称作临界资源。属于临界资源的硬件有,打印机,磁带机等;软件有消息队列,变量,数组,缓冲区等。诸进程间采取互斥方式,实现对这种资源的共享。 二.临界区: 每个进程中访问临界资源的那段代码称为临界区(criticalsection ) ,每次只允许一个进程进入临界区,进入后,不允许其他进程进入。不论是硬件临界资源还是软件临界资源,多个进程必须互斥的对它进行访问。多个进程涉及到同一个临界资源的的临界区称为相关临界区。使用临界区时,一般不允许其运行时间过长,只要运行在临界区的线程还没有离开,其他所有进入此临界区的线程都会被挂起而进入等待状态,并在一定程度上影响程序的运行性能。 三、优缺点 优点:效率高, 与互斥和事件这些内核同步对象相比,临界区是用户态下的对象,即只能在同一进程中实现线程互斥。因无需在用户态和核心态之间切换,所以工作效率比较互斥来说要高很多。 缺点:资源释放容易出问题 ,Critical Section不是一个核心对象,无法获知进入临界区的线程是生是死,如果进入临界区的线程挂了,没有释放临界资源,系统无法获知,而且没有办法释放该临界资源。 临界区是一种轻量级的同步机制,与互斥和事件这些内核同步对象相比,临界区是用户态下的对象, 即只能在同一进程中实现线程互斥

windows多线程同步--临界区

浪子不回头ぞ 提交于 2020-03-16 14:33:30
推荐参考博客: 秒杀多线程第五篇 经典线程同步 关键段CS 关于临界区的观念 ,一般操作系统书上面都有。 适用范围:它只能同步一个进程中的线程,不能跨进程同步。一般用它来做单个进程内的代码快同步,效率比较高 windows中与临界区有关的结构是 CRITICAL_SECTION,关于该结构体的内部结构可参考 here 使用时,主线程中要先初始化临界区,最后要删除临界区,具体使用见下面代码: 本文地址 从一个例子来说明:假设有三个线程都需要使用打印机,我们可以把打印的代码放到临界区,这样就可以保证每次只有一个线程在使用打印机。 #include<string> #include<iostream> #include<process.h> #include<windows.h> using namespace std; //定义一个临界区 CRITICAL_SECTION g_cs; //线程绑定的函数返回值和参数是确定的,而且一定要__stdcall unsigned __stdcall threadFun(void *param) { EnterCriticalSection(&g_cs);//进入临界区,如果有其他线程则等待 cout<<*(string *)(param)<<endl; LeaveCriticalSection(&g_cs);//退出临界区,其他线程可以进来了

多线程笔记:同步机制(1)

有些话、适合烂在心里 提交于 2020-03-07 00:22:25
同步机制简介 线程同步机制是一套用于协调线程间的数据访问及活动的机制,该机制用于保障线程安全以及实现这些线程的共同目标。 线程同步机制是编程语言为多线程运行制定的一套规则,合理地运用这些规则可以很大程度上保障程序的正确运行。 这套机制包含两方面的内容,一是关于多线程间的数据访问的规则,二是多线程间活动的规则。前者关乎程序运行的正确与否,是相当重要的内容;后者很大程度上是影响程序的运行效率,也是不容忽视的内容。不太严谨地说,数据访问的规则主要是由锁来实现,线程间活动的规则则表现线程调度上。 锁 线程安全问题的产生前提是多个线程并发访问共享数据,那么一种保障线程安全的方法就是将多个线程对共享数据的并发访问转换为串行访问,即一个共享数据一次只能被一个线程访问,该线程访问结束后其他线程才能对其进行访问。锁就是利用这种思路来实现线程同步机制。 GoLang中换了个思路,通过通道(channel)来实现共享数据的安全性。 锁的相关概念 锁在编程里是个蛮有趣的概念。 锁:置于可启闭的器物上,以钥匙或暗码(如字码机构、时间机构、自动释放开关、磁性螺线管等)打开的扣件 —— 在线新华字典 特定代码的作用域或是 lock() 和 unlock() 方法之间的代码构成的区域就是“器物”的表征,线程访问其中的共享数据相当于解开“扣件”,打开了“器物”;通常所说“获得xx锁”,更像是获得了“钥匙或暗码

L17 信号量临界区保护

痞子三分冷 提交于 2020-02-29 19:32:00
为什么要保护信号量和临界区? 在现实中如何保护信号量和临界区? empty = -1:的含义? 表示有一个进程正在睡眠 为什么要保护? 进程中存在一种调度,使得信号量引发错误。所以要保护! 怎么保护信号量? 要上锁 什么是临界区? 当一个进程在进入一段代码时,另外一个进程不能进入对应的修改信号的代码。所以出现了保护修改信号量的临界区。 临界区代码的保护原则? 临界区怎样设计呢? 方法一 用一个轮换法试试? 这种方法满足互斥要求,但是P 0 执行之后,没有进程P 1 了,P 0 无法继续执行。所以不行!!! 方法二 标记法: 每一个进程都有一个标记,进入的时候把自己的标记标为true,判断 互斥吗? 互斥,P0进入时:flag[0] = true;flag[1] = false; P1进入时:flag[1] = true;flag[0] = false; 但是有问题 如果按照(1)(2)(3)(4)执行,谁都进不去临界区 还是不行,怎么做呢? 方法三 改一下, 非对称标记 进入临界区Peterson算法(这个算法真聪明) 结合了标记和轮转两种思想:(值日加标记·) 多进程怎么办?—面包店算法(不懂) 临界区保护另外一种解法:关中断,和开中断 也存在问题,当出现多CPU时,一个CPU关闭中断,另一个CPU仍然可以执行P i 进程,这种策略不好使,但是在单CPU种很方便。

锁的升级打怪:通俗易懂讲解偏向锁、轻量级锁和重量级锁

青春壹個敷衍的年華 提交于 2020-02-25 14:43:57
PART0: PART1: 首先通过一个小例子来解释一下三种锁的区别: 假如家里只有一个碗,当我自己在家时,没有人会和我争碗,这时即为偏向锁状态 当我和女朋友都在家吃饭时,如果女朋友不是很饿,则她会等我吃完再用我的碗去吃饭,这就是轻量级锁状态 当我和女朋友都很饿的时候,这时候就会去争抢这唯一的一个碗(贫穷的我)吃饭,这就是重量级锁状态 PART2: 我是一个线程,生活在JVM(Java虚拟机)中, 这一段日子过得有些无聊,整个世界似乎只有这一个人,天天忙着执行代码,想休息一下都很难。 我听说人类写的代码中有些特殊的地方,叫做 临界区 ,比如synchronized修饰的方法或者代码块,他们非常神奇,在同一时刻JVM老大只允许一个线程进入执行。 实际上,老大设置了一把锁,抢到了这把锁就可以执行,否则只能阻塞,等待别人释放锁。 老大说,阻塞就是不用干活了,老老实实地等着就行。 竟然还有这等美事! 赶紧让我阻塞一次吧。 可是老大又说:“每次设置锁我都得和操作系统打交道,请他在内核中维护一个什么Mutex(互斥量)的东西,他还得把你们这些线程阻塞,切换,这可是一笔巨大的费用啊,所以这些锁还是少用为妙。” 我运气也不好,我不知道执行了多少代码,调用了多少函数,竟然一次也没遇到临界区! 我想也许这个程序员编程时不小心,没有考虑多线程并发的情况; 也有可能是这些程序大部分都是无状态的