7. 初步认识线程同步

news2024/11/15 15:27:57

前言:一旦接触到多线程编程,那么线程之间的同步就显得非常重要了。c++/c#/java等高级语言都有自己的线程库,当然也提供了线程同步的API接口。打个比方,在C++/QT中,线程的同步有以下几种方式:互斥锁、信号量、条件变量、读写锁等。基于不同语言的库所提供的线程同步的接口大同小异。总体来说,只要掌握了线程同步的基本思想,那么在每种语言中都可以使用的起来,不同的只是接口上的差异(例如命名、参数、返回值等等)

1. python中的线程同步

如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间。

# 我们来看这样一个demo, 假如我们有100张火车票需要出售, 有2个窗口同时出售(相当于2个线程),
# 无论如何, 两个窗口都不可能出售票号相同的一张票.

import threading

g_tickets = 100


def fun1():
    while True:
        global g_tickets
        if g_tickets > 0:
            print('thread_1 sell ticket: ', g_tickets)
            g_tickets -= 1


def fun2():
    while True:
        global g_tickets
        if g_tickets > 0:
            print('thread_2 sell ticket:', g_tickets)
            g_tickets -= 1


t1 = threading.Thread(target=fun1, args=())
t2 = threading.Thread(target=fun2, args=())

t1.start()
t2.start()

t1.join()
t2.join()

在这里插入图片描述
通过程序运行结果发现, 票号为96的这张票被2个线程分别出售了一次,如果是在真实的火车售票系统中出现这种问题,那麻烦就大了。
那为啥会有这种问题出现?
  分析:这是由于在多CPU的平台下,线程1和线程2在被创建后可以并发运行,全局变量g_tickets被卖到96号票的时候,此时线程1正在售卖,然后线程1还没来得及对g_tickets进行自减就切换到线程2了,很明显,此时线程2也对96号票进行了售卖于是造成了2个线程分别对96号票进行了售卖的这样情况上述问题出现的主要原因是两个线程同时访问了同一个全局变量:g_tickets为了避免这种问题的发生,就要求在多个 线程之间进行一个同步处理,保证在一个线程访问共享资源时,其他线程不能访问该共享资源。对于本例来说,就是当一个线程在销售火车票的时候,其他线程在该段时间内不能访问同一种资源,本例就是全局变量g_tickets,必须等到前者完成火车票的售卖过程之后,其他线程才能访问该资源。这与我们上厕所一样,假如3个人共用一个厕所,其中有一个人在使用时,其他人必须依次排队等候,这样就不会造成冲突了,否则非打起来不可。


程序改进:有了以上的分析之后,我们知道为了避免此种情况发生,必须进行线程同步。
为此我们引入 threading.Lock()函数,通过该lock()函数可以获取锁。
然后通过acquire()进行上锁,通过release()来释放锁。
将需要保护的代码放到acquire()...release()之间,就可以实现线程同步的效果

import threading

g_tickets = 100


def fun1():
    while True:
        lock.acquire()	# 加锁
        global g_tickets
        if g_tickets > 0:
            print('thread_1 sell ticket: ', g_tickets)
            g_tickets -= 1
        lock.release() # 释放锁


def fun2():
    while True:
        lock.acquire() # 加锁
        global g_tickets
        if g_tickets > 0:
            print('thread_2 sell ticket: ', g_tickets)
            g_tickets -= 1
        lock.release() # 释放锁


lock = threading.Lock() #获取锁

t1 = threading.Thread(target=fun1, args=())
t2 = threading.Thread(target=fun2, args=())

t1.start()
t2.start()

t1.join()
t2.join()

在这里插入图片描述
此时,我们再来对96号票分析一下
假如此时线程1正在贩卖96号票,那么很明显,此时线程1对这个锁进行了上锁操作,并且正在执行售卖过程,但是还未自减;此时突然线程调度,切换到了线程2,线程2也想进行上锁操作,要想进行上锁操作,那必须先拿取到锁才行,但是很明显,此时的锁被线程1给上锁了(占有了),还没有被线程1所释放,那么线程2只能苦苦的等待拿锁,阻塞在lock.acquire()处等待线程1对锁进行释放,然后它可能有机会拿取到锁(不一定拿取到),然后进行上锁操作,进行售卖过程。这样一来,共享资源g_tickets就在线程1 和线程2之间实现了同步,也就是同一时间只能有一个线程操作它。这样就不会出现之前的问题了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/181598.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2、SPSS的基本知识

目录 一、SPSS软件的安装和启动 二、SPSS的基本操作环境 (1)数据编辑窗口(主程序窗口) (2)SPSS结果输出窗口 三、SPSS软件的退出 四、SPSS软件的三种基本使用方式 五、SPSS数据的结构和定义方法 1.…

单链表——简单的增删查改

前言:上次介绍了顺序表,这次我要分享对单链表的一些简单理解,主要框架与上次大致相同,内容主要是单链表的增删查改,适用于初学者,之后会继续更新一些更深入的内容。同时,这也仅仅是我个人对所学…

不完全微分PID控制算法及仿真

在 PID控制中,微分信号的引入可改善系统的动态特性,但也易引进高频干扰,在误差扰动突变时尤其显出微分项的不足。若在控制算法中加入低通滤波器,则可使系统性能得到改善。克服上述缺点的方法之一是在 PID算法中加入一个一阶惯性环…

pdf如何合并,用这个方法又快又好使

我们在整理文档的时候经常被要求最后提交的得是PDF,所以有时候手头上的文档有多份,但最后还得整合成一份PDF才行。合并PDF后我们才可以进行后续的操作,所以学会如何快速合并PDF很重要。要把多个文档整合到一起,借助下面这些工具就…

一文带你了解学习python的用处及好处,建议收藏

目录 学习Python能做什么? Python的用途有哪些 普通人学习python有什么好处 用处,很重要的呢 今天这一讲很关键,如果你都不知道python的好处,以及python的用处,那你python就算是白学了 学习Python能做什么&#xf…

【目标检测】------rcnn、fastrcnn、fasterrcnn

RCNN流程图 sppnet流程图 fastRcnn fasterrcnn网络 RPN(Region Proposal Network)是Faster-RCNN网络用于提取预选框(也就是RCNN中使用selective search算法进行Region Proposal的部分),我们知道RCNN及Fast-RCNN中一个…

【Maven】属性管理

1. 属性 问题导入 定义属性有什么好处&#xff1f; 1.1 属性配置与使用 ①&#xff1a;定义属性 <!--定义自定义属性--> <properties><spring.version>5.2.10.RELEASE</spring.version><junit.version>4.12</junit.version> </prop…

第二章——CSS基础选择器,标签选择器,类选择器, id 选择器,通配符选择器

文章目录2.1 CSS选择器的作用2.2 CSS选择器分类2.3 CSS 基础选择器分类2.4 标签选择器2.5 类选择器2.5.1 多类名选择2.6 id选择器2.7 id选择器与类选择器的区别‘2.8 通配符选择器2.9 选择器对比2.1 CSS选择器的作用 选择器(选择符)就是根据不同需求把不同的标签选出来这就是选…

python图像处理(直方图增强)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 前面几篇文章谈到了对图像的处理,但是它们大多数都是对图像像素进行一些时空的转换,本身像素的内容并没有发生转变。比如旋转,镜像、移动、放大、缩小等等,像素还是这些像素,只…

Pytorch基础知识

Pytorch 基础知识 1.1 张量的概念 在PyTorch中&#xff0c;张量&#xff08;Tensor&#xff09;属于一种数据结构&#xff0c;它可以使一个标量、一个向量、一个矩阵&#xff0c;甚至是更维度的数组。类似于numpy中的数组 (ndarray),并且它们是可以相互转化的&#xff0c;在P…

python3:openpyxl解析和生成excel的常用方法

解析 打开已经存在的工作簿 openpyxl.load_workbook()方法 from openpyxl import load_workbookwb2 load_workbook(test.xlsx) print wb2.get_sheet_names() [Sheet2, New Title, Sheet1] 生成 创建一个工作簿 from openpyxl import Workbook# 一个工作簿(workbook)在创建…

kafka的关键细节 以及 分区和主题的概念

文章目录Kafka中的关键细节1.消息的顺序存储2. 单播消息的实现3.多播消息的实现4.查看消费组及信息主题、分区的概念1.主题Topic2.partition分区Kafka中的关键细节 1.消息的顺序存储 消息的发送方会把消息发送到broker中&#xff0c;broker会存储消息&#xff0c;消息是按照发…

python本科毕业设计基于神经网络的虚假评论识别系统源码,含模型及数据

主要函数&#xff1a; 1.corpusprocess原始语料处理函数 2.train_word2vec生成word2vec向量 3.generate_id2wec获得索引的w2id,和嵌入权重embedding_weights 4.prepare_data 数据预处理 完整代码下载地址&#xff1a;python本科毕业设计基于神经网络的虚假评论识别系统源码 代…

多线程(初阶)——多线程基础

多线程(初阶)——多线程基础 文章目录多线程(初阶)——多线程基础1.认识线程2.多线程程序2.1 第一个Java多线程程序2.2 观察线程的详细情况2.3 sleep方法2.4 run和start方法的区别3.创建线程3.1 继承Thread类3.2实现Runnable接口3.3 通过匿名内部类创建线程3.4通过实现Runnable…

【目标检测】------yolox网络结构

YOLOX网络结构图 卷积和池化计算器&#xff1a; http://www.sqflash.com/cal.html

ServletAPI 2-10复杂参数, 解析完的参数值都会放到 ModelAndViewContainer里面

总结&#xff1a; 找到解析器后&#xff0c;用解析器去解析参数&#xff0c;都使用了resolveArgument()中以下方法 mavContainer.getModel(); mavContainer:模型和视图容器 视图&#xff1a;页面请求要返回一个地方&#xff0c;这个地方的地址叫视图 。比如要到/sucess 模…

CV——day70 零基础学YOLO:YOLOv1

YOLO系列1. 不同阶段算法优缺点分析2. IOU指标计算3. MAP指标计算**指标分析**如何计算MAP4 YOLOv14.1 YOLOv1核心思想4.2 YOLOv1网络架构那么&#xff0c;7 * 7 * 30的输出是怎么来呢&#xff1f;4.3 损失函数4.3.1 位置误差4.3.2 置信度误差(含object)4.3.3 置信度误差(不含o…

股票量化分析工具QTYX使用攻略——小市值轮动选股策略(更新2.5.9)

搭建自己的量化交易系统 如果要长期在市场中立于不败之地&#xff01;必须要形成一套自己的交易系统。 如何学会搭建自己的量化交易系统&#xff1f; 边学习边实战&#xff0c;在实战中学习才是最有效地方式。于是我们分享一个即可以用于学习&#xff0c;也可以用于实战炒股分析…

Springboot农产品特产销售网站maven mysql idea

摘 要 I 1 绪论 1 1.1研究背景 1 1.2研究现状 1 1.3研究内容 2 2 系统关键技术 3 2.1 JSP技术 3 2.2 JAVA简介 3 2.3 MYSQL数据库 4 2.4 B/S结构 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2经济可行性 5 3.1.3操作可…

[Android开发基础2] 七大常用界面控件(附综合案例)

文章目录 一、文本TextView 二、按钮Button 三、编辑输入框EditText 四、图片ImageView 五、单选按钮RadioButton 六、复选框CheckBox 七、系统消息框Toast 综合案例&#xff1a;账号注册界面 一、文本TextView TextView控件用于显示文本信息。 演示&#xff1a; <?…