多线程
用到模块threading
简单示例如下:
import time
import threading
def sing():
"""唱歌5秒钟"""
for i in range(5):
print("---正在唱歌---")
time.sleep(1)
def dance():
"""跳舞5秒钟"""
for i in range(5):
print("---正在跳舞---")
time.sleep(1)
def main():
t1 = threading.Thread(target=sing)
t2 = threading.Thread(target=dance)
t1.start() # start() 即让线程开始执行
t2.start()
main()
并行:真的多任务
并发:假的多任务
length = len(threading.enumerate()) # 查看当前程序运行所创建的线程数
# 当长度为1时,意为子线程都完成了任务,则此时可以结束主线程
# 若主线程结束了,则所有子线程都会直接结束
注:当调用Thread的时候,不会创建线程
当调用Thread创建出来的实例对象的start方法的时候,才会去创建线程以及让这个线程开始运行
元组拆包小技巧:
a, b = (11,22)
实际:a=11,b=22
a = [11,22,33]
b = enumerate(a)
for i,name in b:
print(i,num)
通过继承Thread类完成创建线程
代码示例:
import threading
import time
class MyThread(threading.Thread):
def run(self)
for i in range(3):
time.sleep(1)
print("这是%s" % i)
if __name__ == '__main__':
t = MyThread()
t.start() # 调用start()的时候会自动的执行类里面的run方法
创建线程并传入参数
创建线程时传入args参数,args必须是元组
import time
import threading
def test1(temp):
temp.append(33)
print("---正在使用test1函数 参数值为:%s---" % str(temp))
def test2(temp)
print("---正在使用test2函数 参数值为:%s---" % str(temp))
temp_li = [11,22]
def main():
t1 = threading.Thread(target=test1,args=(temp_li,))
t2 = threading.Thread(target=test2,args=(temp_li,))
t1.start()
time.sleep(1)
t2.start()
time.sleep(1)
print("主线程此时temp_li的值为:%s" % str(temp_li))
main()
多线程中资源竞争问题
两个线程对一个变量同时进行写入时,就会出现资源竞争问题,比如对一个变量num=0,两个线程都对num同时进行一百万次加1,最终结果却不是两百万!
def thread1(num):
for i in range(1000000):
num += 1 # 在真正执行的时候会解析成几步
# 1.获取num的值
# 2.把获取的值+1
# 3.把第二步的结果存储到num中
简单来说,线程1和线程2很可能在同时执行第三步,所以这样会导致+1的效果没有起到作用。
解决方法:互斥锁
# 创建锁
mutex = threading.Lock()
# 锁定
mutex.acquire()
# 释放
mutex.release()
对于上述问题,可以直接在num+=1这一步操作中进行上锁与释放锁即可解决
import threading
mutex = threading.Lock()
for i in range(1000000):
mutex.acquire()
num+=1
mutex.release()
**
如果这个锁之前是没有上锁的,那么acquire不会堵塞
如果在调用acquire对这个锁上锁之前,它已经被其他线程上了锁,那么此时acquire会堵塞,直到锁被解锁为止
**