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

作者:Record learning 时间:2022-08-29 04:34:18 

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多线程和多线程变量共享问题介绍

来源:https://blog.csdn.net/qq_40483425/article/details/105521392

标签:python,多线程,变量共享
0
投稿

猜你喜欢

  • 在线Ajax载入动画生成工具 - Loadinfo

    2008-02-18 13:34:00
  • ASP+XML制作菜单管理

    2008-05-19 12:38:00
  • 从trim原型函数看js正则表达式的性能

    2008-12-11 13:55:00
  • SNS用户体验和互动性浅析

    2011-01-17 17:56:00
  • python实现PyEMD经验模态分解残差量分析

    2022-06-22 05:26:17
  • Python sklearn 中的 make_blobs() 函数示例详解

    2022-07-24 21:45:48
  • python+tkinter编写电脑桌面放大镜程序实例代码

    2023-08-02 17:10:43
  • 服务器XMLHTTP(Server XMLHTTP in ASP)基础知识

    2011-03-06 11:11:00
  • Python实现炸金花游戏的示例代码

    2022-01-15 05:24:17
  • Python处理CSV与List的转换方法

    2021-11-22 11:53:48
  • 浅谈DataFrame和SparkSql取值误区

    2021-03-21 22:04:18
  • Python多线程正确用法实例解析

    2022-03-22 14:31:58
  • django美化后台django-suit的安装配置操作

    2021-12-19 23:13:25
  • Python实现基于POS算法的区块链

    2023-10-30 01:47:19
  • Python并发之多进程的方法实例代码

    2022-04-13 12:43:54
  • python使用KNN算法手写体识别

    2022-06-28 05:30:56
  • 对Python 文件夹遍历和文件查找的实例讲解

    2021-11-05 22:29:25
  • python内置模块OS 实现SHELL端文件处理器

    2023-11-24 16:41:14
  • Python Web框架Flask中使用新浪SAE云存储实例

    2022-11-03 06:27:16
  • python随机模块random的22种函数(小结)

    2022-08-11 18:09:03
  • asp之家 网络编程 m.aspxhome.com