多线程的特点与同步、互斥锁
线程之间执行是无序的
线程执行是根据cpu调度决定的
线程之间执行是无序的
# #导入线程模块
# import threading
# #导入时间模块
# import time
#Thread线程类参数
# target:执行的任务名
# args:以元组的形式给任务传参
# kwargs:以字典的形式给任务传参# def task():
# time.sleep(1)
# print("当前线程是:",threading.current_thread().name) #显示当前线程对象名
# if __name__ == '__main__':
# for i in range(5):
# # 每循环一次就创建一个子线程
# t = threading.Thread(target=task)
# # 启动子线程
# t.start()
线程之间共享资源
# li = [] #定义全局变量
# # 写入数据
# def wdata():
# for i in range (5):
# li. append (i)
# time.sleep (1)
# print('写入的数据是:',li)
# #读取数据
# def rdata():
# print('读取的数据是:',li)
# if __name__ == '__main__':
# #创建子线程
# wd = threading.Thread(target=wdata)
# rd = threading.Thread(target=rdata)
# #开启子线程
# wd.start()
# wd.join() #阻塞线程
# rd.start()
# rd.join()# 线程之间共享资源(全局变量)
#
# # from threading import Thread #导入线程模块
# import threading
# import time
# li = [] #定义全局变量
# # 写入数据
# def wdata():
# for i in range (5):
# li. append (i)
# time.sleep (0.2)
# print('写入的数据是:',li)
# #读取数据
# def rdata():
# print('读取的数据是:',li)
# if __name__ == '__main__':
# #创建子线程
# t1 = threading.Thread(target=wdata)
# t2 = threading.Thread(target=rdata)
# #开启子线程
# t1.start()
# #阻塞线程
# # t1.join() #加了join()就会等待t1任务执行结束
# time.sleep(1) #时间一定要匹配 time.sleep(0.8)
# t2.start()
# t2.join()
#
资源竞争
#导入线程模块
import threading
#导入时间模块
import time# a = 0
# b = 10000000
# def add():
# for i in range (b):
# global a #Python 中的 global关键字主要用于在函数内部声明一个变量为全局变量,从而允许你在函数内部读取、修改在函数外部定义的全局变量,而不是创建一个新的局部变量
#
# a+=1
# print('第一次累加:',a)
#
# def add2():
# for i in range (b):
# global a
# a+=1
# print('第二次累加:',a)
#
# # add()
# # add2()
# if __name__ == '__main__':
# a1=threading.Thread(target=add)
# a2 = threading.Thread(target=add2)
# a1.start()
# a2.start()
#
# # 数大了之后计算机计算不过来就会抢资源,导致算错 资源竞争#资源竞争
#
# from threading import Thread
# # import threading
#
# a=0
# b=1000000
# #循环一次就给全局变量a+1
# def add():
# for i in range (b):
# global a
# a+=1
# print("第一次:",a)
# # add()
#
# def add2():
# for i in range (b):
# global a
# a+=1
# print("第二次:",a)
#
#
# add() #第一次100000
# add2() #第二次200000
#
# if __name__ == '__main__':
# first = Thread(target=add)
# second = Thread(target=add2)
# first.start()
# second.start()#资源竞争
#
# from threading import Thread
# # import threading
#
# a=0
# b=1000000
# #循环一次就给全局变量a+1
# def add():
# for i in range (b):
# global a
# a+=1
# print("第一次:",a)
# # add()
#
# def add2():
# for i in range (b):
# global a
# a+=1
# print("第二次:",a)
#
#
# add() #第一次100000
# add2() #第二次200000
#
# if __name__ == '__main__':
# first = Thread(target=add)
# second = Thread(target=add2)
# first.start()
# second.start()
线程同步
主线程和创建的子线程之间各自执行完自己的代码直至结束
1.线程等待
2.互斥锁
线程等待
# #导入线程模块
# import threading
# #导入时间模块
# import time# a = 0
# b = 10000000
# def add():
# for i in range (b):
# global a #Python 中的 global关键字主要用于在函数内部声明一个变量为全局变量,从而允许你在函数内部读取、修改在函数外部定义的全局变量,而不是创建一个新的局部变量
# a+=1
# print('第一次累加:',a)
#
# def add2():
# for i in range (b):
# global a
# a+=1
# print('第二次累加:',a)
#
# if __name__ == '__main__':
# a1=threading.Thread(target=add)
# a2 = threading.Thread(target=add2)
# a1.start()
# a1.join() #等待a1子线程执行结束以后,代码再继续往下运行,开始执行a2子线程
# a2.start()
# a2.join()
#
互斥锁
概念:对共享数据进行锁定,保证多个线程访问共享数据不会出
现数据错误问题:保证同一时刻只能有一个线程去操作。
方法:
acquire():上锁
release():释放锁
注意:这两个方法必须成对出现,否则容易形成死锁。
#导入线程模块
# import threading
#导入时间模块
# import time
#导入互斥锁模块
from threading import Lock
#1.创建全局互斥锁
lock = Lock()
a = 0
b = 10000000
def add():#2.上锁lock.acquire()for i in range (b):global a #Python 中的 global关键字主要用于在函数内部声明一个变量为全局变量,从而允许你在函数内部读取、修改在函数外部定义的全局变量,而不是创建一个新的局部变量a+=1print('第一次累加:',a)#3.释放锁lock.release()def add2():# 2.上锁lock.acquire()for i in range (b):global aa+=1print('第二次累加:',a)# 3.释放锁lock.release()if __name__ == '__main__':a1=threading.Thread(target=add)a2 = threading.Thread(target=add2)a1.start()#a1.join() #等待a1子线程执行结束以后,代码再继续往下运行,开始执行a2子线程a2.start()#a2.join()
总结
1.互斥锁的作用:保证同一个时刻只有一个线程去操作共享数据,保证共享数据不会出现错误问题
2.上锁和释放锁必须成对出现,否则容易造成死锁现象
死锁:一直等待对方释放锁的情景就是 死锁会造成应用程序停止响应,不能再处理其他任务 3.互斥锁的缺点:会影响代码的执行效率