Python 线程 的 锁

Python  线程 的 锁Python  线程 的 锁     目录
  • 锁的使用姿势
  • 锁 的作用
  • 防止死锁产生
  • 全局锁GIL
    锁的使用姿势
姿势一:
  • threading.Lock()  :  来创建锁对象
  • acquire()  :获取锁
  • release()  :   释放锁
 
import threading
 
#创建锁对象
lock = threading.Lock()
 
#获取锁
lock.acquire()
 
#释放锁
lock.release()

 

解释: acquire()  和  release()  是成对出现的。往往死锁的出现就是  release 没有执行       姿势二:
  • threading.Loc() : 创建锁对象
  • with :  上下文管理器来获取,释放锁
 
import  threading
 
lock = threading.Lock()
 
with lock:
    #业务代码
    pass
  解释: with  是可以 自动 获取锁 和 释放锁的,可以防止我们忘记释放锁而造成死锁的情况发生     锁的作用
    锁的 核心作用 就是为了保证数据的 一致性 ,对锁内的资源(变量)进行锁定,避免其它线程偷偷进行 篡改 。以达到我们的预期效果。即: 异步变同步。   用例一:   Python  线程 的 锁Python  线程 的 锁   解析:     由于线程是内核级别的,它的切换是由CPU说了算,两线程间的执行顺序是完全没有约束的,轮到谁了就谁上。所以整个结果是无序的。   用例二: Python  线程 的 锁Python  线程 的 锁   解析:
  • work1 由于先启动,它先锁定了资源
  • work2 切换进来的时候,发现资源是锁定的,所以它只能继续等待
  • work2 会在  “切换”与“等待”这两个状态间进行轮替,直到work1 释放锁
  所以,我们看到的执行顺序一直就是图上的结果了。这样也就达到了我们的预期效果了。     防止死锁产生
    死锁的原因是多种多样的,但是本质就是对资源不合理的竞争锁导致的。 死锁的常见原因:
  • 同一个线程  : 嵌套获取同一把锁,导致获取释放锁不合理而造成死锁
  • 多个线程     :    不安顺序同事获取多个锁,造成死锁
  第一种就不用说了,这里介绍一下第二种情况: 前提条件
  • 线程1 : 嵌套获取  A  , B  两个锁
  • 线程2 :   嵌套获取  B , A 两个锁
      执行情况
  • 线程1 获取了A  锁 , 而没有获取B 锁
  • 线程2  获取了B  锁 , 而没有获取A  锁
  执行结果
  • 线程1  在等待线程2 释放B 锁 然后结束任务,
  • 线程2 在等待  线程1  释放A 锁, 然后结束任务
  • 最终两个线程就陷入了相互等待的局面了。这个就是死锁
            用例一:     Python  线程 的 锁Python  线程 的 锁     全局锁
    我们都知道 多进程是真正的并行执行 , 多线程只是交替执行。     python 中导致 线程 交替执行的是一个叫  GIL 【Global Interpreter Lock】全局锁 的东西          什么GIL?          Python 在线程执行前,必须加上一个  GIL  锁, 然后,每执行100条字节码, 解释器就释放GIL 锁, 让别的线程有机会执行。这个GIL 全局锁实际上把 所有 线程的执行代码都上锁了,所以,多线程在Python 中只能交替执行 , 即使是100 个线程跑在了 100核的CPU 上,也只有一个核在运算。          注意,GIL 不是Python 本身的特性,而是它的解析器之一的 CPython 的特性。 Python 的解析器还有: PyPy , Psyco , JPython 等。只是我们绝大多数情况下,都是使用的是CPython 这个解析器,所以也就默认了 Python 有  GIL 这个特性了。        都知道GIL 影响性能, 那么如何避免受到  GIL 的影响?
  •  使用多进程代替多线程
  •  更换Python 解析器, 不使用  CPython   
    另外, Python  的线程在I/O 开销比较大的情况下,优势还是特别明显的。                    
上一篇:多线程Web服务器上的python wsgi:这是竞争条件吗?


下一篇:如何在python中压缩一个非常大的文件