线程安全问题
一、造成线程安全问题的原因:
GIL全局解释器锁
每个线程在执行时候都需要先获取GIL,保证同一时刻只有一个线程可以执行代码,即同一时刻只有一个线程使用CPU,也就是说python的多线程并不是真正意义上的同时执行。
二、多线程共享全局变量
Python多线程是通过threading模块来实现的。
在一个进程内的所有线程共享全局变量,很方便在多个线程间共享数据。
from threading import Thread
list_a = [1, 2, 3]
def add_list():
global list_a
list_a.append(100)
print(list_a)
if __name__ == '__main__':
t1 = Thread(target=add_list)
t2 = Thread(target=add_list)
print(t1.name)
t1.start()
print(t2.name)
t2.start()
Thread-1
[1, 2, 3, 100]
Thread-2
[1, 2, 3, 100, 100]
三、多线程的资源竞争问题(线程非安全)
在多个线程对全局变量进行修改时,造成得到的结果不正确,这种情况就是线程安全问题。
from threading import Thread
num = 0
def run1():
global num
for i in range(1000000):
num += 1
def run2():
global num
for i in range(1000000):
num += 1
if __name__ == '__main__':
t1 = Thread(target=run1,name="t1")
t2 = Thread(target=run2,name="t2")
t1.start()
t2.start()
print(num)
运行结果 :748795 每次还都不相同
四、怎么解决多线程竞争问题?---最简单的同步机制是使用互斥锁
# 某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改。直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行操作,从而保证了多线程情况下数据的正确性。
*注意:
多个线程使用的是同一个锁,如果数据没有被锁锁上,那么acquire()方法不会堵塞,会执行上锁操作。如果在调用acquire时,数据已经被其他线程上了锁,那么acquire()方法会堵塞,直到数据被解锁为止。
*上锁解锁过程:
"""
1、当一个线程调用锁的acquire()方法获得锁时,锁就进入“locked”状态。
2、每次只有一个线程可以获得锁。如果此时另一个线程试图获得这个锁,该线程就会变为“blocked”状态,称为“阻塞”,直到拥有锁的线程调用锁的release()方法释放锁之后,锁进入“unlocked”状态。
3、线程调度程序从处于同步阻塞状态的线程中选择一个来获得锁,并使得该线程进入运行(running)状态。
"""
from threading import Thread, Lock, enumerate
import time
num = 0
mutex = Lock()
def add_num():
global num
for i in range(100000):
mutex.acquire()
num += 1
mutex.release()
if __name__ == '__main__':
t1 = Thread(target=add_num)
t2 = Thread(target=add_num)
t3 = Thread(target=add_num)
t1.start()
t2.start()
t3.start()
while len(enumerate()) != 1:
time.sleep(1)
print(num)
五、死锁及解决方法
python中在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁,因为系统判断这部分资源都正在使用,所有这两个线程在无外力作用下将一直等待下去。
为了支持在同一线程中多次请求同一资源,python提供了"递归锁":threading.RLock。RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次acquire。直到一个线程所有的acquire都被release,其他的线程才能获得资源。
标签:__,Thread,t2,t1,问题,安全,num,线程 From: https://www.cnblogs.com/DTCLOUD/p/17360946.html作者:钱煜