小编这次要给大家分享的是解决python多线程和多线程变量共享问题,文章内容丰富,感兴趣的小伙伴可以来了解一下,希望大家阅读完这篇文章之后能够有所收获。

1、demo

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

import threadingimport timeclass 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:breaktime.sleep(1)if __name__ == '__main__':main()

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

2、多线程共享变量

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

import threadingimport time#定义全局变量g_num = 0def test1():"""函数test1对全局变量进行更改"""global g_numfor i in range(1,10):g_num += 1print("--- 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()# 增加睡眠是为了保证优先执行函数test1time.sleep(1)t2.start()print("--- 主线程 g_num = %d--- " % g_num)if __name__ == '__main__':main()

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

3、资源竞争

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

import threadingimport time# 定义全局变量g_num = 0def test1(num):"""函数test1对全局变量进行更改"""global g_numfor i in range(num):g_num += 1print("test1 线程 g_num = %d---" % g_num)def test2(num):"""函数test2对全局变量进行更改"""global g_numfor i in range(num):g_num += 1print("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

4、互斥锁

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

import threadingimport time# 创建变量g_num = 0# 创建锁默认为开锁状态mutex = threading.Lock()def test1(num):global g_numfor i in range(num):# 上锁mutex.acquire()g_num += 1# 解锁mutex.release()print("--- test1 线程 g_num = %d---" % g_num)def test2(num):global g_numfor 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()

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

5、死锁

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

import threadingimport time# 创建两个锁A, BmutexA = 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多线程和多线程变量共享问题的文章,如果觉得文章内容写得不错的话,可以把它分享出去给更多人看到。