返回顶部
首页 > 资讯 > 后端开发 > Python >11.python并发入门(part3
  • 634
分享到

11.python并发入门(part3

入门python 2023-01-31 06:01:52 634人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

一、锁的概念。锁,通常被用来实现共享数据的访问,为每一个共享的数据,创建一个Lock对象(一把锁),当需要访问这个共享的资源时,可以调用acquire方法来获取一个锁的对象,当共享资源访问结束后,在调用release方法去解锁。二、pyth

一、的概念。

锁,通常被用来实现共享数据的访问,为每一个共享的数据,创建一个Lock对象(一把锁),当需要访问这个共享的资源时,可以调用acquire方法来获取一个锁的对象,当共享资源访问结束后,在调用release方法去解锁。


二、python中的互斥锁。

在介绍互斥锁之前,先来一起看一个例子。(每个线程对num实现一次-1的操作)

import threading

import  time

num = 200  #每个线程都共享这个变量。

tread_list = []

def count_num():

    global num  #每个线程都去获取这个全局变量。

    temp_num = num

    time.sleep(0.1) #执行sleep,相当于执行io操作.

    num = temp_num - 1 #对公共的变量做一个-1的操作。

for i in range(200):      #同时开启200个线程

    t = threading.Thread(target=add_num)

    t.start()

    tread_list.append(t)

for t in tread_list:

    t.join()

print "ending....num = %s" %(num)


最后的结果就是:

ending....num = 199

结果并不是我们想要的。来分析下为何会出现这种现象。

200个线程现在想统一修改一个全局变量,由于Python解释器的GIL锁的限制,每次只能有一个线程在cpu上运行,在执行到sleep时,就相当于一次I/O操作,这时就会切到其他的线程,在执行sleep之前,当前运行的这个线程,这个线程取到的全局变量的值是200(temp_num = 200),还没来得及做修改,就被切换到其他线程了,其他的线程也是一样的道理,取到temp_num = 200这个值后,还没来得及计算,执行到sleep触发一次IO操作后,又切到了其他的线程,第2个第3个直到最后一个线程都拿到了temp_num=200这个变量后,后面的计算操作才会开始运行!(不要忘记一个概念,线程在切换之前,是会保存当前执行状态的)当所有线程都拿到了emp_num=200这个变量后,每个线程都会自己执行一遍

num = temp_num - 1这也就导致了每个线程执行的都是200-1 所以,最后的结果就等于199.


例子2.还拿刚刚写的那个减法程序举例,我们把sleep的时间缩短为0.001秒看看会出现什么效果?

还是上一段代码,只不过把count_num函数的time.sleep(0.1)改为time.sleep(0.001)看看出现了什么效果。


我们把执行过程也输出一下:

i am Thread-1 , set num 200

i am Thread-2 , set num 200

i am Thread-3 , set num 200

i am Thread-4 , set num 200

i am Thread-5 , set num 200

i am Thread-6 , set num 200

i am Thread-7 , set num 200

i am Thread-8 , set num 200

i am Thread-9 , set num 200

i am Thread-10 , set num 200

i am Thread-11 , set num 199

i am Thread-12 , set num 199

i am Thread-13 , set num 198

i am Thread-14 , set num 198

i am Thread-15 , set num 197

i am Thread-16 , set num 197

i am Thread-17 , set num 197

i am Thread-18 , set num 197

i am Thread-19 , set num 196

i am Thread-20 , set num 196

i am Thread-21 , set num 196

i am Thread-22 , set num 195

i am Thread-23 , set num 195

i am Thread-24 , set num 194

i am Thread-25 , set num 194

i am Thread-26 , set num 194

i am Thread-27 , set num 193

i am Thread-28 , set num 193

i am Thread-29 , set num 192

i am Thread-30 , set num 192

i am Thread-31 , set num 192

i am Thread-32 , set num 191

i am Thread-33 , set num 190

i am Thread-34 , set num 189

i am Thread-35 , set num 189

i am Thread-36 , set num 188

i am Thread-37 , set num 187

i am Thread-38 , set num 186

i am Thread-39 , set num 186

i am Thread-40 , set num 185

i am Thread-41 , set num 185

i am Thread-42 , set num 184

i am Thread-43 , set num 184

i am Thread-44 , set num 184

i am Thread-45 , set num 184

i am Thread-46 , set num 184

i am Thread-47 , set num 183

i am Thread-48 , set num 182

i am Thread-49 , set num 182

i am Thread-50 , set num 181

i am Thread-51 , set num 179

i am Thread-52 , set num 179

i am Thread-53 , set num 179

i am Thread-54 , set num 179

i am Thread-55 , set num 177

i am Thread-56 , set num 177

i am Thread-57 , set num 177

i am Thread-58 , set num 177

i am Thread-59 , set num 177

i am Thread-60 , set num 176

i am Thread-61 , set num 175

i am Thread-62 , set num 175

i am Thread-63 , set num 174

i am Thread-64 , set num 174

i am Thread-65 , set num 174

i am Thread-66 , set num 174

i am Thread-67 , set num 173

i am Thread-68 , set num 171

i am Thread-69 , set num 171

i am Thread-70 , set num 171

i am Thread-71 , set num 170

i am Thread-72 , set num 169

i am Thread-73 , set num 168

i am Thread-74 , set num 167

i am Thread-75 , set num 166

i am Thread-76 , set num 166

i am Thread-77 , set num 165

i am Thread-78 , set num 165

i am Thread-79 , set num 165

i am Thread-80 , set num 165

i am Thread-81 , set num 164

i am Thread-82 , set num 164

i am Thread-83 , set num 163

i am Thread-84 , set num 162

i am Thread-85 , set num 162

i am Thread-86 , set num 162

i am Thread-87 , set num 160

i am Thread-88 , set num 159

i am Thread-89 , set num 159

i am Thread-90 , set num 158

i am Thread-91 , set num 157

i am Thread-92 , set num 156

i am Thread-93 , set num 156

i am Thread-94 , set num 156

i am Thread-95 , set num 156

i am Thread-96 , set num 156

i am Thread-97 , set num 155

i am Thread-98 , set num 154

i am Thread-99 , set num 154

i am Thread-100 , set num 154

i am Thread-101 , set num 153

i am Thread-102 , set num 152

i am Thread-103 , set num 152

i am Thread-104 , set num 151

i am Thread-105 , set num 151

i am Thread-106 , set num 151

i am Thread-107 , set num 151

i am Thread-108 , set num 150

i am Thread-109 , set num 149

i am Thread-110 , set num 149

i am Thread-111 , set num 149

i am Thread-112 , set num 149

i am Thread-113 , set num 149

i am Thread-114 , set num 149

i am Thread-115 , set num 149

i am Thread-116 , set num 149

i am Thread-117 , set num 149

i am Thread-118 , set num 149

i am Thread-119 , set num 149

i am Thread-120 , set num 149

i am Thread-121 , set num 149

i am Thread-122 , set num 149

i am Thread-123 , set num 148

i am Thread-124 , set num 147

i am Thread-125 , set num 147

i am Thread-126 , set num 145

i am Thread-127 , set num 145

i am Thread-128 , set num 145

i am Thread-129 , set num 144

i am Thread-130 , set num 143

i am Thread-131 , set num 142

i am Thread-132 , set num 142

i am Thread-133 , set num 142

i am Thread-134 , set num 142

i am Thread-135 , set num 142

i am Thread-136 , set num 142

i am Thread-137 , set num 141

i am Thread-138 , set num 141

i am Thread-139 , set num 141

i am Thread-140 , set num 140

i am Thread-141 , set num 140

i am Thread-142 , set num 139

i am Thread-143 , set num 139

i am Thread-144 , set num 139

i am Thread-145 , set num 139

i am Thread-146 , set num 138

i am Thread-147 , set num 138

i am Thread-148 , set num 137

i am Thread-149 , set num 136

i am Thread-150 , set num 136

i am Thread-151 , set num 136

i am Thread-152 , set num 136

i am Thread-153 , set num 136

i am Thread-154 , set num 135

i am Thread-155 , set num 135

i am Thread-156 , set num 135

i am Thread-157 , set num 134

i am Thread-158 , set num 133

i am Thread-159 , set num 133

i am Thread-160 , set num 133

i am Thread-161 , set num 133

i am Thread-162 , set num 132

i am Thread-163 , set num 131

i am Thread-164 , set num 131

i am Thread-165 , set num 131

i am Thread-166 , set num 131

i am Thread-167 , set num 131

i am Thread-168 , set num 130

i am Thread-169 , set num 130

i am Thread-170 , set num 130

i am Thread-171 , set num 130

i am Thread-172 , set num 129

i am Thread-173 , set num 127

i am Thread-174 , set num 127

i am Thread-175 , set num 127

i am Thread-176 , set num 127

i am Thread-177 , set num 127

i am Thread-178 , set num 126

i am Thread-179 , set num 126

i am Thread-180 , set num 125

i am Thread-181 , set num 124

i am Thread-182 , set num 124

i am Thread-183 , set num 124

i am Thread-184 , set num 124

i am Thread-185 , set num 123

i am Thread-186 , set num 122

i am Thread-187 , set num 122

i am Thread-188 , set num 122

i am Thread-189 , set num 122

i am Thread-190 , set num 122

i am Thread-191 , set num 121

i am Thread-192 , set num 120

i am Thread-193 , set num 119

i am Thread-194 , set num 118

i am Thread-195 , set num 118

i am Thread-196 , set num 118

i am Thread-197 , set num 118

i am Thread-198 , set num 118

i am Thread-199 , set num 117

i am Thread-200 , set num 116

ending....num = 115

这个结果完全出乎意料,最终num变成了115。

接着来分析下造成这种结果的原因。

当sleep时间较短的时候,在线程切换的过程中,之前运行的线程的sleep就已经执行结束了,就会重新参与竞争cpu资源,在切得过程中,之前的线程sleep结束,就有了被切回去的可能,继续执行后面的num = temp_num - 1 所以就会导致这种情况。


注意!!这里面的sleep是用来模拟程序中的I/O操作!


从第二个例子中,我们可以看到一个全局资源被抢占的现象,没有控制多个线程对一个全局资源的访问控制,造成全局资源的损坏(这里的损坏是指得到了我们不想要的结果)使我们无法预测程序最后执行的结果,如果想避免这种问题,就需要用到“互斥锁”。

“互斥锁”最主要的作用就是,保证在操作共享数据时,共享数据的完整性。

互斥锁实现的方式,就是为每个共享的资源创建一个Lock对象,当需要访问这个共享资源的时候,调用

这个锁的acquire方法来获取锁的对象,资源访问结束后,在调用release方法去解锁。

我们对上面的程序进行整改,为此我们需要添加一个互斥锁变量t_lock = threading.Lock(),然后在争夺资源的时候之前我们会先抢占这把锁t_lock.acquire(),对资源使用完成之后我们在释放这把锁t_lock.release().

#!/usr/local/bin/python2.7

# -*- coding:utf-8 -*-

import threading

import  time

num = 1000

tread_list = []

t_lock = threading.RLock()  #创建一个锁的对象。

def add_num():

    global num,temp_num

    if t_lock.acquire():   #加锁

        temp_num = num

        time.sleep(0.001) #执行sleep,相当于执行IO操作.

        num = temp_num - 1

        t_lock.release()  #公共资源访问和操作结束后,解锁。

for i in range(200):

    t = threading.Thread(target=add_num)

    t.start()

    tread_list.append(t)

for t in tread_list:

    t.join()

print "ending....num = %s" %(num)


最后看下输出结果:

ending....num = 0

之前的资源抢占现象得到了解决。


当一个线程去调用一个Lock对象的acquire()方法去得到一个锁时,这把锁就会进入一个“locked”锁定的状态,在锁定时,每次只有一个线程可以获得锁,如果有第二个线程试图去获得锁(去访问操作共享资源时),去操作共享的数据时,第二个线程就会进入阻塞状态,直到线程1对共享数据资源操作结束后,调用了这个lock对象的release方法后(此时的锁已经变为“unlocked”状态),线程二才可以去操作共享资源。


大概的加锁思路就是这样的:

import threading

R=threading.Lock()  #创建一个锁的对象

R.acquire() #加锁

'''

对公共数据的操作    #执行了对公共数据的操作后

'''

R.release() #解锁


最后补充~

写到这里,可能会有人觉得,互斥锁和join没什么区别!!事实并非如此!

互斥锁可以做到,只有对公共数据进行访问或者操作的时候是串行模式!

如果使用了join,那么两个线程中所有执行的操作都会变为串行模式!!

这两个还是有很大区别的!



--结束END--

本文标题: 11.python并发入门(part3

本文链接: https://lsjlt.com/news/189466.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 11.python并发入门(part3
    一、锁的概念。锁,通常被用来实现共享数据的访问,为每一个共享的数据,创建一个Lock对象(一把锁),当需要访问这个共享的资源时,可以调用acquire方法来获取一个锁的对象,当共享资源访问结束后,在调用release方法去解锁。二、pyth...
    99+
    2023-01-31
    入门 python
  • J2EE入门(11) (转)
    J2EE入门(11) (转)[@more@]一般问题和解决方案 不能启动J2EE Server 命名和目录服务端口冲突 症状:当你用-verbose选项启动J2EE server,它显示这些行: J2EE server listen por...
    99+
    2023-06-03
  • python web开发入门
    Ps:2019-1-18修改 我其实对这篇文章能有两万+的阅读量感觉很惊讶,占了我博客访问人数的很大一部分,我猜测可能确实是传统的Python web开发的学习方式都是从框架开始,而框架封装过度,让人难以理解背后的原理,最后只是简...
    99+
    2023-01-31
    入门 python web
  • Python并发编程入门:Linux环境学习笔记!
    在计算机科学中,并发是指在同一时间段内处理多个任务的能力。并发编程在现代计算机系统中至关重要,因为它可以提高系统的性能和响应能力。Python是一种流行的编程语言,它支持多线程和多进程并发编程。在本篇文章中,我们将学习如何在Linux环境...
    99+
    2023-07-07
    linux 学习笔记 并发
  • Oracle专题11之PLSQL入门
    1、PLSQL工具 PL/SQL Developer的简介:PL/SQL Developer是一种专门用于开发、测试、调试和优化Oracle PL/SQL的一种工具,更是一个非常好用的Oracle的管理工...
    99+
    2024-04-02
  • 深入浅出:Python并发编程入门指南,带你领略并发编程的魅力
    1. Python中的并发编程 Python提供了几种并发编程模型,每种模型都有自己的特点和适用场景。最常用的并发编程模型包括: 线程:线程是操作系统提供的并发执行单元,每个线程都有自己的独立栈空间,但共享相同的堆空间。线程之间可以共...
    99+
    2024-02-05
    Python 并发 线程 多进程 协程
  • java并发编程的入门过程
    本篇文章给大家分享的是有关java并发编程的入门过程,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1、入门介绍1.1、实现线程的2种方式package chapter...
    99+
    2023-06-19
  • Python asyncio 入门:用优雅的方式编写并发代码
    在当今快节奏的数字世界中,构建高性能、响应迅速的应用程序至关重要。Python asyncio 模块提供了一种优雅的方式,使开发人员能够编写并发代码,充分利用现代多核处理器。通过使用非阻塞 I/O 和事件循环,asyncio 可以在不牺...
    99+
    2024-03-03
    Python asyncio 并发异步编程 网络编程
  • Python入门
    ---恢复内容开始---   在这章中,我了解到了计算机的概念、Python的发展史以及Python语言的版本之间的区别,并自己安装了Python的编辑器。通过安装Python编辑器,我认识到安装软件也可以在官网上安装。     在第...
    99+
    2023-01-30
    入门 Python
  • python 入门
    1、 python 脚本的编写   文件:hello.py   第一步:在第一行添加  #!/usr/bin/env python #!/usr/bin/env python3 print("hello world");    第二步...
    99+
    2023-01-30
    入门 python
  • 《Python 并发编程有多难?git 能否帮助你快速入门?》
    Python 并发编程有多难?git 能否帮助你快速入门? 随着计算机硬件的发展,我们的软件需求也越来越复杂,比如要同时处理多个任务,或者是需要快速响应用户请求。这就需要我们使用并发编程来解决问题。而 Python 作为一门高级编程语言,提...
    99+
    2023-11-12
    git 并发 教程
  • 《Python 并发编程从入门到精通:如何利用 git 学习?》
    Python 并发编程从入门到精通:如何利用 git 学习? Python 是一门高效、易用的编程语言,越来越多的人开始学习和使用它。而并发编程是 Python 的一个重要领域,掌握并发编程可以让我们更好地利用计算机的多核性能,提高程序的效...
    99+
    2023-11-12
    git 并发 教程
  • 开发者如何快速入门Python
    今天就跟大家聊聊有关开发者如何快速入门Python,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Python确实是个好语言,这点毋庸置疑, Python一直以简洁方便而又强大著称,其...
    99+
    2023-06-17
  • mac python学习开发简单入门
    安装 Mac自带python 在/usr/bin/python 进入终端直接键入python即可进入交互模式 或是python xxx.py 运行 写好的python程序 Last login: Sat Aug 19 20...
    99+
    2023-01-31
    入门 简单 mac
  • python开发工具pycharm快速入门
    本教程是关于什么的本教程旨在引导您完成创建,运行和调试一个简单的Python项目,使用PyCharm一步一步 - Python的IDE有一整套完整的生产性的开发工具。本教程不是关于哪些的Python编程超出了本教程的范围。要了解更多关于Py...
    99+
    2023-06-02
  • 学python入门有用吗?Python全栈开发
      随着云计算时代的到来,如何在应用程序开发的同时筛选有意义的数据以进行专业处理也逐渐成为每个开发企业需要考虑的问题。随着Python编程语言的兴起,越来越受企业的喜爱,也吸引了大量的人们开始学习,并进入it互联网领域。  什么是Pytho...
    99+
    2023-06-02
  • ESP8266入门教程11:连接MQTT服务器
    将第三方库PubSubClient下载到lib文件夹 git clone https://github.com/knolleary/pubsubclient.git 一、阿里云IOT使用 打开阿里云IOT官网,登录阿里云账号 http...
    99+
    2023-10-18
    c++ 物联网 单片机 阿里云
  • 深入了解Python并发编程
    目录并发方式线程([Thread])进程 (Process)远程分布式主机 (Distributed Node)伪线程 (Pseudo-Thread)实战运用计算密集型IO密集型总结...
    99+
    2024-04-02
  • 【Python】PyQt5入门
    文章目录 0 前言1 PyQt5及其基本模块2 开发方式3 UI界面设计(Qt Designer)4 逻辑代码的基本结构5 常用控件及其使用方法5.1 QTableView //2023.4....
    99+
    2023-10-20
    python qt pyqt5 qt designer TableView刷新数据
  • Python入门 (二)
    本文是个人python学习笔记,学习资料为廖雪峰python教程,如需更多内容,请移步廖老师官方网站。 一 函数式编程Functional Programming 函数式编程允许把函数本身作为参数传入另一个函数,还允许返回一个函数。Pyt...
    99+
    2023-01-31
    入门 Python
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作