线程锁
多线程共享资源导致竞争的问题可以使用线程同步来解决
1.系统调用t1,然后取到num的值,此时为访问上一把锁,即不允许其他线程操作num
2.t1操作num
3.t1解锁,其他线程可以继续使用num,且此时num的值为t1操作后的结果
4.同理在每一个线程访问num时,都要先上锁,访问完成后再解锁,以此保证同一时间只有一个线程在使用资源
发生资源竞争的原因:
线程的调度是根据系统分配的时间来进行的,此时间可能切断正在进行的修改操作,导致一个修改的中间插入了另一个修改,插入的修改被覆盖
互斥锁根据锁定和解锁的位置,来控制其中的操作完整进行
互斥锁
当多个线程几乎同时修改某一个共享数据时,需要进行同步控制
线程同步能够保证多个线程安全访问竞争资源,最简单的实现方法是引入互斥锁
互斥锁为资源引入一个状态:锁定/非锁定
某个线程需要修改共享资源时,先将资源的状态设为锁定,其他线程不能修改,直到该线程释放资源,将资源的状态设为非锁定
互斥锁保证了每次只有一个线程进行写入操作,从而保护多线程情况下数据的正确性
如果在调用obj.acquire()上锁之前,已经被其他线程上了锁,那么此acquire将会阻塞,直到这个锁被解锁
死锁
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源,且同时等待对方的资源,就会造成死锁
死锁很少发生,但一旦发生就会导致应用停止响应
import threading
import time
# 互斥锁
num = 0
def work1():
global num
lock1.acquire()
for i in range(100000):
num += 1
lock1.release()
print('work1----------',num)
def work2():
global num
for i in range(100000):
lock1.acquire()
num += 1
lock1.release()
print('work2----------',num)
if __name__ == '__main__':
# 创建锁
lock1 = threading.Lock()
t1 = threading.Thread(target=work1)
t2 = threading.Thread(target=work2)
# t1.start()
# t2.start()
# while len(threading.enumerate()) != 1:
# time.sleep(1)
# print('main----------',num)
# 死锁
# 如果在return之前不释放锁,return后锁定状态就会保持,等待解锁的线程会一直阻塞
def get_value(index):
l = [1,3,5,7,9]
lock1.acquire()
# 判断索引是否合法
if index >= len(l):
print('索引超出列表范围:',index)
lock1.release()
return
print(l[index])
lock1.release()
if __name__ == '__main__':
lock1 = threading.Lock()
for i in range(10):
t1 = threading.Thread(target=get_value,args=(i,))
t1.start()
work1---------- 100000
work2---------- 200000
main---------- 200000
1
3
5
7
9
索引超出列表范围: 5
索引超出列表范围: 6
索引超出列表范围: 7
索引超出列表范围: 8
索引超出列表范围: 9