浅谈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统计日志中每个IP出现次数的方法
Jul 06 Python
Python基于pygame实现的font游戏字体(附源码)
Nov 11 Python
python多线程方式执行多个bat代码
Jun 07 Python
python 网络编程详解及简单实例
Apr 25 Python
python实现简单flappy bird
Dec 24 Python
对python mayavi三维绘图的实现详解
Jan 08 Python
python使用tkinter库实现五子棋游戏
Jun 18 Python
python批量处理文件或文件夹
Jul 28 Python
Python爬虫requests库多种用法实例
May 28 Python
OpenCV+python实现实时目标检测功能
Jun 24 Python
Python基于xlutils修改表格内容过程解析
Jul 28 Python
对Keras自带Loss Function的深入研究
May 25 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
牡丹941资料
2021/03/01 无线电
PHP4在WinXP下IIS和Apache2服务器上的安装实例
2006/10/09 PHP
PHP防止注入攻击实例分析
2014/11/03 PHP
通过php动态传数据到highcharts
2017/04/05 PHP
使用jquery给input和textarea设定ie中的focus
2008/05/29 Javascript
告诉大家什么是JSON
2008/06/10 Javascript
js判断变量是否空值的代码
2008/10/26 Javascript
jquery实现图片左右间隔滚动特效(可自动播放)
2013/05/08 Javascript
快速解决jQuery与其他库冲突的方法介绍
2014/01/02 Javascript
PHPExcel中的一些常用方法汇总
2015/01/23 Javascript
给angular加上动画效遇到的问题总结
2016/02/17 Javascript
javascript数组去重方法分析
2016/12/15 Javascript
基于JavaScript实现选项卡效果
2017/07/21 Javascript
ES6使用Set数据结构实现数组的交集、并集、差集功能示例
2017/10/31 Javascript
nodejs微信开发之自动回复的实现
2019/03/17 NodeJs
Swiper.js实现移动端元素左右滑动
2019/09/08 Javascript
Javascript中的this,bind和that使用实例
2019/12/05 Javascript
JS实现简易贪吃蛇游戏
2020/08/24 Javascript
python中元类用法实例
2014/10/10 Python
Python实现的ini文件操作类分享
2014/11/20 Python
在Python的Django框架中生成CSV文件的方法
2015/07/22 Python
python使用SMTP发送qq或sina邮件
2017/10/21 Python
python制作填词游戏步骤详解
2019/05/05 Python
详解Python的循环结构知识点
2019/05/20 Python
Python3 A*寻路算法实现方式
2019/12/24 Python
python绘制雷达图实例讲解
2021/01/03 Python
收集的7个CSS3代码生成工具
2010/04/17 HTML / CSS
html5开发三八女王节表白神器
2018/03/07 HTML / CSS
李维斯法国官网:Levi’s法国
2019/07/13 全球购物
2014新课程改革心得体会
2014/03/10 职场文书
气象学专业个人求职信
2014/04/22 职场文书
初一学生期末评语
2014/04/24 职场文书
2015秋季小学开学寄语
2015/05/27 职场文书
看上去很美观后感
2015/06/10 职场文书
上个世纪50年代的可穿戴技术:无线电帽子
2022/02/18 无线电
动画电影《擅长捉弄人的高木同学》6月10日上映!
2022/03/20 日漫