浅谈python多线程和多线程变量共享问题介绍


Posted in Python onApril 17, 2020

1、demo

第一个代码是多线程的简单使用,编写了线程如何执行函数和类。

import threading
import time
class ClassName(threading.Thread):
	"""创建类,通过多线程执行"""
	def run(self):
		for i in range(5):
			print(i)
			time.sleep(1)

def sing():
	for i in range(1,11):
		print("唱歌第 %d 遍" % i)
		time.sleep(1)

def dance():
	for i in range(1,16):
		print("跳舞第 %d 遍" % i)
		time.sleep(1)

def main():
	t1 = threading.Thread(target = sing)
	t2 = threading.Thread(target = dance)
	t = ClassName()
	
	# 启动线程
	t1.start()
	t2.start()
	t.start()

	while True:
		length = len(threading.enumerate())
		print("正在运行的线程有 %s" %threading.enumerate())
	
		if length <= 1:
			break
		time.sleep(1)

if __name__ == '__main__':
	main()

执行结果可以看到函数 sing、dance和类在同时执行,执行效果太长就不方截图了

2、多线程共享变量

通过定义全局变量,然后再test1函数类部进行更改全局变量,test2打印全局变量。

import threading
import time

#定义全局变量
g_num = 0

def test1():
	"""函数test1对全局变量进行更改"""
	global g_num
	for i in range(1,10):
		g_num += 1

	print("--- test1 线程 g_num = %d--- " % g_num)

def test2():
	"""函数test2 打印全局变量"""
	print("--- test2 线程 g_num = %d--- " % g_num)

def main():
	t1 = threading.Thread(target=test1)
	t2 = threading.Thread(target=test2)

	# 启动线程
	t1.start()
	# 增加睡眠是为了保证优先执行函数test1
	time.sleep(1)
	t2.start()

	print("--- 主线程 g_num = %d--- " % g_num)

if __name__ == '__main__':
	main()

执行结果可以看出,在主线程和创建的两个线程中读取的是一样的值,既可以表明在多线程中变量共享

浅谈python多线程和多线程变量共享问题介绍

3、资源竞争

在多线程两个函数中同时更改一个变量时,由于cpu的计算能力,当修改参数的代码块无法一次性执行完成时,就会产生资源竞争

import threading
import time

# 定义全局变量
g_num = 0

def test1(num):
	"""函数test1对全局变量进行更改"""
	global g_num
	for i in range(num):
		g_num += 1

	print("test1 线程 g_num = %d---" % g_num)

def test2(num):
	"""函数test2对全局变量进行更改"""
	global g_num
	for i in range(num):
		g_num += 1

	print("tes2 线程 g_num = %d---" % g_num)

def main():
	t1 = threading.Thread(target=test1, args=(1000000, ))
	t2 = threading.Thread(target=test2, args=(1000000, ))

	t1.start()
	t2.start()

	time.sleep(1)
	print("主线程 g_num = %d---" % g_num)

if __name__ == '__main__':
	main()

可以先试试传递参数为100时,可以看到g_num = 200 这是因为函数代码可以一次性执行完成,当参数为1000000时代码无法一次性执行完成,g_num!= 2000000

浅谈python多线程和多线程变量共享问题介绍

4、互斥锁

互斥锁可以解决资源竞争的问题,原理很简单,通过对代码块上锁,保证该代码执行完成前,其它代码无法进行修改。执行完成后解锁,其它代码就可以执行了。

import threading
import time

# 创建变量
g_num = 0
# 创建锁默认为开锁状态
mutex = threading.Lock()

def test1(num):
	global g_num
	for i in range(num):
		# 上锁
		mutex.acquire()
		g_num += 1
		# 解锁
		mutex.release()
	print("--- test1 线程 g_num = %d---" % g_num)

def test2(num):
	global g_num
	for i in range(num):
		# 上锁
		mutex.acquire()
		g_num += 1
		# 解锁
		mutex.release()

	print("--- test2 线程 g_num = %d---" % g_num)

def main():
	t1 = threading.Thread(target=test1, args=(1000000, ))
	t2 = threading.Thread(target=test2, args=(1000000, ))

	t1.start()
	t2.start()

	time.sleep(1)
	print("--- 主线程 g_num = %d---" % g_num)

if __name__ == '__main__':
	main()

可以看到加了锁之后,代码执行不会出现资源竞争,结果也是正常的。互斥锁,上锁的代码越少越好。

浅谈python多线程和多线程变量共享问题介绍

5、死锁

当出现多个锁时,就可能会产生死锁这个情况。当关闭一个锁时,这个锁已经为关闭状态的话,程序就会阻塞。就如同下面这个代码中。函数test1关闭mutexB锁时,函数test2提前将其关闭了,未进行解锁,程序就会一直阻塞。

import threading
import time

# 创建两个锁A, B
mutexA = threading.Lock()
mutexB = threading.Lock()

def test1():
	# 对muctexA上锁
	mutexA.acquire()

	# mutexA上锁后,延时1秒,等待mutexB上锁
	print("test1 ---do1---up---")
	time.sleep(1)
	# 此时会堵塞,因为mutexB已经上锁
	mutexB.acquire()
	print("test1 ---do1---down---")
	mutexB.release()

	# 对mutexA解锁
	mutexA.release()

def test2():
	# 对muctexB上锁
	mutexB.acquire()

	# mutexB上锁后,延时1秒,等待mutexA上锁
	print("test2 ---do1---up---")
	time.sleep(1)
	# 此时会堵塞,因为mutexB已经上锁
	mutexA.acquire()
	print("test2 ---do1---down---")
	mutexA.release()

	# 对mutexA解锁
	mutexB.release()

def main():
	t1 = threading.Thread(target=test1)
	t2 = threading.Thread(target=test2)

	t1.start()
	t2.start()


if __name__ == '__main__':
	main()

代码执行效果可以看到程序会一直阻塞
解决方法
1、在程序编写时,就需要注意避免死锁
2、可以参考银行家算法

浅谈python多线程和多线程变量共享问题介绍

到此这篇关于浅谈python多线程和多线程变量共享问题介绍的文章就介绍到这了,更多相关python 多线程变量共享内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python生成ppt的方法
Jun 07 Python
Python脚本修改阿里云的访问控制列表的方法
Mar 08 Python
简单了解Python matplotlib线的属性
Jun 29 Python
python实现网站微信登录的示例代码
Sep 18 Python
Python使用xpath实现图片爬取
Sep 16 Python
python爬虫---requests库的用法详解
Sep 28 Python
详解tensorflow之过拟合问题实战
Nov 01 Python
scrapy在python爬虫中搭建出错的解决方法
Nov 22 Python
python基于pexpect库自动获取日志信息
Feb 01 Python
Python实现8种常用抽样方法
Jun 27 Python
python中的3种定义类方法
Nov 27 Python
讲解Python实例练习逆序输出字符串
May 06 Python
使用Matplotlib绘制不同颜色的带箭头的线实例
Apr 17 #Python
matplotlib 曲线图 和 折线图 plt.plot()实例
Apr 17 #Python
Python实现自动打开电脑应用的示例代码
Apr 17 #Python
Python matplotlib绘制图形实例(包括点,曲线,注释和箭头)
Apr 17 #Python
Python读取excel文件中带公式的值的实现
Apr 17 #Python
在Matplotlib图中插入LaTex公式实例
Apr 17 #Python
python中for in的用法详解
Apr 17 #Python
You might like
社区(php&amp;&amp;mysql)六
2006/10/09 PHP
用PHP即时捕捉PHP中的错误并发送email通知的实现代码
2013/01/19 PHP
php用户注册页面利用js进行表单验证具体实例
2013/10/17 PHP
preg_match_all使用心得分享
2014/01/31 PHP
PHP获取redis里不存在的6位随机数应用示例【设置24小时过时】
2017/06/07 PHP
身份证号码前六位所代表的省,市,区, 以及地区编码下载
2007/04/12 Javascript
jQuery判断元素是否是隐藏的代码
2011/04/24 Javascript
屏蔽相应键盘按钮操作
2014/03/10 Javascript
Javascript让DEDECMS告别手写Tag
2014/09/01 Javascript
jQuery获得包含margin的outerWidth和outerHeight的方法
2015/03/25 Javascript
jquery实现手风琴效果
2015/11/20 Javascript
关于JavaScript和jQuery的类型判断详解
2016/10/08 Javascript
利用jQuery实现滑动开关按钮效果(附demo源码下载)
2017/02/07 Javascript
JavaScript拖动层Div代码
2017/03/01 Javascript
jquery中each循环的简单回滚操作
2017/05/05 jQuery
js实现数组和对象的深浅拷贝
2017/09/30 Javascript
解决vue this.$forceUpdate() 处理页面刷新问题(v-for循环值刷新等)
2018/07/26 Javascript
javascript实现fetch请求返回的统一拦截
2019/12/22 Javascript
Vue如何实现监听组件原生事件
2020/07/03 Javascript
微信小程序实现自定义底部导航
2020/11/18 Javascript
python PyQt5/Pyside2 按钮右击菜单实例代码
2019/08/17 Python
Django admin 实现search_fields精确查询实例
2020/03/30 Python
Tensorflow tf.nn.atrous_conv2d如何实现空洞卷积的
2020/04/20 Python
tensorflow模型文件(ckpt)转pb文件的方法(不知道输出节点名)
2020/04/22 Python
python模拟哔哩哔哩滑块登入验证的实现
2020/04/24 Python
如何用python处理excel表格
2020/06/09 Python
手把手教你用Django执行原生SQL的方法
2021/02/18 Python
使用CSS3实现圆角,阴影,透明
2014/12/23 HTML / CSS
HTML5边玩边学(3)像素和颜色
2010/09/21 HTML / CSS
市场营销专业毕业生自荐信
2013/11/02 职场文书
贷款委托书怎么写
2014/08/02 职场文书
大学生读书笔记大全
2015/07/01 职场文书
python爬取网页版QQ空间,生成各类图表
2021/06/02 Python
mysql数据插入覆盖和时间戳的问题及解决
2022/03/25 MySQL
Python下载商品数据并连接数据库且保存数据
2022/03/31 Python
Redis 报错 error:NOAUTH Authentication required
2022/05/15 Redis