多线程
t=threading.Thread(target=task,arge=(11,))
start()开始
join()等待
主线程在默认情况下会等待所有非守护线程(子线程)结束后才会结束程序。也就是说,如果主线程在结束前没有调用所有子线程的 join()
方法,主线程将继续执行,并且当主线程完成它的执行后,它将等待所有子线程结束。
多线程对同一个变量操作时可能造成数据竞争
python
import threading
loop=1000000
number=0
def _add(count):
global number
for i in range(count):
number+=1
def _sub(count):
global number
for i in range(count):
number-=1
t1=threading.Thread(target=_add,args=(loop,))
t2=threading.Thread(target=_sub,args=(loop,))
t1.start()
t2.start()
t1.join()
#t2.join()
print(number)
未调用 t2.join()
会导致在 t1
线程结束后,主线程打印 number
的值,然后程序依然会等 t2
线程结束。但由于打印 number
的操作在 t2
结束前可能被执行,这会导致 number
的值不确定。
解决方案:
加锁
python
import threading
loop=1000000
number=0
lock_object=threading.RLock()
def _add(count):
lock_object.acquire() #申请锁
global number
for i in range(count):
number+=1
lock_object.release() # 释放锁
def _sub(count):
lock_object.acquire()
global number
for i in range(count):
number-=1
lock_object.release()
# 也可以这么写
def sub():
with lock_object: #自动进行申请和释放
global number
for i in range(count):
number-=1
t1=threading.Thread(target=_add,args=(loop,))
t2=threading.Thread(target=_sub,args=(loop,))
t1.start()
t2.start()
t1.join()
t2.join()
print(number)
Lock(同步锁)和 RLock(递归锁)区别
Lock效率更高,但是不支持多次锁的情况,一般项目开发还是用RLock
python
import threading
lock_object=threading.RLock()
# personA create a function
def fun():
with lock_object:
pass
# personB,too and use A' fun()
def run():
print("other use")
fun()
print("other use")
# personC create functions,need lock,use fun
def progress():
with lock_object:
print('other use')
fun()
print('hhhhh')
死锁
竞争资源
python
import threading
lock=threading.RLock()
num=0
def task():
print('start')
lock.acquire()
lock.acquire()
global num
for i in range(100000):
num+=i
lock.release()
lock.release()
print(num)
for i in range(2):
t=threading.Thread(target=task)
t.start()
# start
# 4999950000
# start
# 9999900000
彼此通信
python
import threading
import time
lock_1=threading.RLock()
lock_2=threading.RLock()
def task1():
lock_1.acquire()
time.sleep(1)
lock_2.acquire()
print(11)
lock_2.release()
print(1111)
lock_1.release()
print(111111)
def task2():
lock_2.acquire()
time.sleep(1)
lock_1.acquire()
print(22)
lock_1.release()
print(2222)
lock_2.release()
print(222222)
t1=threading.Thread(target=task1)
t1.start()
t2=threading.Thread(target=task2)
t2.start()