浅谈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实现比较两个列表(list)范围
Jun 12 Python
使用python实现BLAST
Feb 12 Python
Window 64位下python3.6.2环境搭建图文教程
Sep 19 Python
python判断文件是否存在,不存在就创建一个的实例
Feb 18 Python
在Python中如何传递任意数量的实参的示例代码
Mar 21 Python
Django框架首页和登录页分离操作示例
May 28 Python
详解pandas删除缺失数据(pd.dropna()方法)
Jun 25 Python
Python单元测试与测试用例简析
Nov 09 Python
Mac PyCharm中的.gitignore 安装设置教程
Apr 16 Python
基于python实现生成指定大小txt文档
Jul 20 Python
小结Python的反射机制
Sep 28 Python
python神经网络 使用Keras构建RNN训练
May 04 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
基于simple_html_dom的使用小结
2013/07/01 PHP
ajax+php控制所有后台函数调用
2015/07/15 PHP
CodeIgniter开发实现支付宝接口调用的方法示例
2016/11/14 PHP
Three.js源码阅读笔记(物体是如何组织的)
2012/12/27 Javascript
jQuery中(function(){})()执行顺序的理解
2013/03/05 Javascript
jQuery常用操作方法及常用函数总结
2014/06/19 Javascript
javascript+canvas制作九宫格小程序
2014/12/28 Javascript
JavaScript阻止浏览器返回按钮的方法
2015/03/18 Javascript
详解JavaScript中Date.UTC()方法的使用
2015/06/12 Javascript
JS实现图片局部放大或缩小的方法
2016/08/20 Javascript
Javascript中call,apply,bind方法的详解与总结
2016/12/12 Javascript
javascript工厂模式和构造函数模式创建对象方法解析
2016/12/30 Javascript
javascript 删除数组元素和清空数组的简单方法
2017/02/24 Javascript
浅谈node模块与npm包管理工具
2018/01/03 Javascript
JS实现继承的几种常用方式示例
2019/06/22 Javascript
JavaScript函数重载操作实例浅析
2020/05/02 Javascript
python实现学生信息管理系统
2020/04/05 Python
我就是这样学习Python中的列表
2019/06/02 Python
python对csv文件追加写入列的方法
2019/08/01 Python
Pandas DataFrame中的tuple元素遍历的实现
2019/10/23 Python
基于Python实现扑克牌面试题
2019/12/11 Python
NumPy排序的实现
2020/01/21 Python
python如何编写类似nmap的扫描工具
2020/11/06 Python
详解css3自定义滚动条样式写法
2017/12/25 HTML / CSS
英国最大的女士服装零售商:Bonmarché
2017/08/17 全球购物
亚洲在线旅行门户网站:Expedia.com.hk(智游网)
2020/04/14 全球购物
使用C#编写创建一个线程的代码
2013/01/22 面试题
酒店前厅员工辞职信
2014/01/08 职场文书
个人查摆剖析材料
2014/02/04 职场文书
军训口号
2014/06/13 职场文书
房屋产权证明书
2014/10/15 职场文书
竞聘报告优秀范文
2014/11/06 职场文书
广告业务员岗位职责
2015/02/13 职场文书
英语专业毕业论文答辩开场白
2015/05/27 职场文书
教你使用TensorFlow2识别验证码
2021/06/11 Python
JavaScript文档对象模型DOM
2021/11/20 Javascript