1.问什么要用线程锁?
因为并发的存在我们不能保证线程内的某段代码执行完毕之后再去执行其他代码,而且对于线程共享的数据我们不能确保他的安全,所以我们通过加线程锁(给代码加锁)来保证线程安全。
2.线程锁应用场景?
IO密集型操作
3.线程锁的分类?
①Lock 同步锁 缺点:不支持多次加锁和解锁,会造成死锁现象
②Rlock 递归锁 用的最多
③BoundedSemaphore(n) 信号量 在创建锁的时候规定好一次能通过几个线程
④Condition() 条件锁
lock.notify(n) 动态的,用户指定个数
lock.wait_for(条件) 当条件满足时就解锁
⑤Event() 红绿灯
lock.wait() 红灯,线程阻塞
lock.set() 绿灯,线程继续执行
lock.clear() 变回红灯,线程阻塞
4.线程锁和GIL的区别?
看图:
线程锁是在线程层面上,GIL全局解释器大锁,就算线程过了线程锁,还是要受GIL大锁的约束
6.代码展示
1.Lock
import threading
import time
lock = threading.Lock()
def test(arg):
#这样写的话程序会阻塞,因为Lock不支持多次加锁和解锁,会造成死锁
lock.acquire()
time.sleep(0.5)
lock.acquire()
print(arg)
lock.release()
lock.release()
for i in range(10):
t = threading.Thread(target=test,args=(i,))
t.start()
2.Rlock
import threading
import time
lock = threading.RLock()
lock1 = threading.Lock()
def test(arg):
#Rlock支持多次加锁和解锁,不会造成死锁
lock.acquire()
time.sleep(0.5)
lock.acquire()
print(arg)
lock.release()
lock.release()
for i in range(10):
t = threading.Thread(target=test,args=(i,))
t.start()
ps:加锁之后一定要解锁,否则程序会阻塞
3.BoundedSemaphore(n)
import threading
import time
lock = threading.BoundedSemaphore(3)
def test(arg):
lock.acquire()
print(arg)
time.sleep(1)
lock.release()
for i in range(10):
t = threading.Thread(target=test,args=(i,))
t.start()
4.Condition()
import threading
import time
lock = threading.Condition()
###方法1
def test(arg):
lock.acquire()
lock.wait()
print(arg)
time.sleep(1)
lock.release()
for i in range(10):
t = threading.Thread(target=test,args=(i,))
t.start()
while True:
ina = input(">>")
lock.acquire()
lock.notify(int(ina)) #根据用户输入来决定要解锁的线程数
lock.release()
###方法2
def operation():
user = input(">>")
td = threading.current_thread()
print(td.getName())
return True
def test(arg):
print("线程进来了")
lock.acquire()
lock.wait_for(operation) #wair_for跟一个条件,等条件执行完毕之后继续往下走
print(arg)
time.sleep(1)
lock.release()
for i in range(10):
t = threading.Thread(target=test,args=(i,))
t.start()
5.Event()
import threading
import time
lock = threading.Event()
def test(arg):
print("线程进来了")
lock.wait()
print(arg)
for i in range(10):
t = threading.Thread(target=test,args=(i,))
t.start()
input(">>")
lock.set() #变绿灯,线程可以继续往下回字形
lock.clear() #变为红灯
for i in range(10): #如果不是值lock.clear(),程序也会执行,因为上边已经将灯变为绿灯了
r = threading.Thread(target=test,args=(i,))
r.start()
input(">>")
lock.set() #变绿灯,线程继续执行