它是一个多线程场景当中的共享变量,虽然说是共享的,但是对于每个线程来说读取到的值都是独立的 。听起来有些难以理解,其实我们可以将它理解成一个dict,dict的key是每一个线程的id,value是一个存储数据的dict 。每个线程在访问local变量的时候,都相当于先通过线程id获取了一个独立的dict,再对这个dict进行的操作 。
看起来我们在使用的时候直接使用了_local,这是因为通过线程id先进行查询的步骤在其中封装了 。不明就里的话可能会觉得有些难以理解 。
我们再来看下这个acquire的使用:
def thread_1():while True:with acquire(x_lock):with acquire(y_lock):print('Thread-1')def thread_2():while True:with acquire(y_lock):with acquire(x_lock):print('Thread-1')
运行一下会发现没有出现死锁的情况,但如果我们把代码稍加调整,写成这样,那么就会触发异常了 。
def thread_1():while True:with acquire(x_lock):with acquire(y_lock):print('Thread-1')def thread_2():while True:with acquire(y_lock):with acquire(x_lock):print('Thread-1')
因为我们把锁写成了层次结构,这样就没办法进行排序保证持有的有序性了,那么就会触发我们代码当中定义的异常 。
最后我们再来看下哲学家就餐问题,通过我们自己实现的acquire函数我们可以非常方便地解决他们死锁吃不了饭的问题 。
import threadingdef philosopher(left, right):while True:with acquire(left,right):print(threading.currentThread(), 'eating')# 叉子的数量NSTICKS = 5chopsticks = [threading.Lock() for n in range(NSTICKS)]for n in range(NSTICKS):t = threading.Thread(target=philosopher,args=(chopsticks[n],chopsticks[(n+1) % NSTICKS]))t.start()
总结关于死锁的问题,对锁进行排序只是其中的一种解决方案,除此之外还有很多解决死锁的模型 。比如我们可以让线程在尝试持有新的锁失败的时候主动放弃所有目前已经持有的锁,比如我们可以设置机制检测死锁的发生并对其进行处理等等 。发散出去其实有很多种方法,这些方法起作用的原理各不相同,其中涉及大量操作系统的基础概念和知识,感兴趣的同学可以深入研究一下这个部分,一定会对操作系统以及锁的使用有一个深刻的认识 。
今天的文章到这里就结束了,如果喜欢本文的话,请来一波素质三连,给我一点支持吧(关注、转发、点赞) 。
推荐阅读
- 3种方法实现python-matplotlib显示中文
- 清朝金瓜子价值 古代金瓜子多少钱
- 宝宝胸口有个窝
- 双顶径股骨长标准
- 九华毛峰多少钱斤,黄山毛峰多少钱斤
- 孕38周胎动多胎心正常
- 胎心变化快
- 菊花茶多少度,菊花茶调散
- 加盟祁门红茶多少钱,祁门红茶的价格是多少
- 手上长痱子怎么办?