[TOC]
一、锁
线程中的锁机制和进程中一样。都是通过锁来控制资源访问虽然,线程中的资源是共享的,但也可以通过锁来进行控制。达到线程同步的目的。虽然牺牲了效率但是保证了安全。
x = 0
mutex = Lock()
def task():
global x
mutex.acquire() # 上锁
for i in range(200000):
x = x +1
mutex.release() # 解锁
if __name__ == '__main__':
th_list = []
for i in range(10):
t1 = Thread(target=task())
t1.start()
th_list.append(t1)
for i in th_list:
i.join()
print(x)
二、解决死锁问题---递归锁
**死锁问题:**死锁就是A等B,B等A,互相都在等锁的开启。因此会造成阻塞。
from threading import Thread,Lock,RLock
# 普通的锁,会出现死锁问题
mutex1 = Lock()
mutex2 = Lock()
import time
class MyThread(Thread):
def run(self):
self.task1()
self.task2()
def task1(self):
mutex1.acquire()
print(f'{self.name} 抢到了 锁1 ')
mutex2.acquire()
print(f'{self.name} 抢到了 锁2 ')
mutex2.release()
print(f'{self.name} 释放了 锁2 ')
mutex1.release()
print(f'{self.name} 释放了 锁1 ')
def task2(self):
mutex2.acquire()
print(f'{self.name} 抢到了 锁2 ')
time.sleep(1) # 出现死锁问题。因为没有执行完,但是mutex1在别的线程中被上锁。mutex2在当前线程中被上锁。
mutex1.acquire()
print(f'{self.name} 抢到了 锁1 ')
mutex1.release()
print(f'{self.name} 释放了 锁1 ')
mutex2.release()
print(f'{self.name} 释放了 锁2 ')
for i in range(3):
t = MyThread()
t.start()
2.1 递归锁
递归锁 同一个线程内可以被多次acquire,但acquire了几次就要release几次内部相当于维护了一个计数器
# 递归锁,可以多次,多次解锁
mutex1 = RLock()
mutex2 = mutex1
import time
class MyThread(Thread):
def run(self):
self.task1()
self.task2()
def task1(self):
mutex1.acquire()
print(f'{self.name} 抢到了 锁1 ')
mutex2.acquire()
print(f'{self.name} 抢到了 锁2 ')
mutex2.release()
print(f'{self.name} 释放了 锁2 ')
mutex1.release()
print(f'{self.name} 释放了 锁1 ')
def task2(self):
mutex2.acquire()
print(f'{self.name} 抢到了 锁2 ')
time.sleep(1) # 出现死锁问题。因为没有执行完,但是mutex1在别的线程中被上锁。mutex2在当前线程中被上锁。
mutex1.acquire()
print(f'{self.name} 抢到了 锁1 ')
mutex1.release()
print(f'{self.name} 释放了 锁1 ')
mutex2.release()
print(f'{self.name} 释放了 锁2 ')
for i in range(3):
t = MyThread()
t.start()
三、信号量
信号量就是加了计数器的锁
代表了同时可以有 多少人 在使用锁
from threading import Thread,currentThread, Semaphore
import time
def task():
sem.acquire()
print(f'{currentThread().name} 在执行')
time.sleep(3)
sem.release()
sem = Semaphore(5)
for i in range(15):
t = Thread(target=task)
t.start()