python锁

Posted 大道至简,小而蕴真

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python锁相关的知识,希望对你有一定的参考价值。

锁的概念是因为多线程而提出的,必须在线程中才能体现出锁的作用。

没用锁的情况:

技术分享图片
import threading
import time

gl_num = 0

def show(arg):
    global gl_num
    n = gl_num
    time.sleep(1)
    gl_num = n+1
    print(gl_num)

for i in range(10):
    t = threading.Thread(target=show, args=(i,))
    t.start()

print (main thread stop)
没用锁的代码
技术分享图片
main thread stop
1
1
1
1
1
1
1
1
1
1
运行结果

可以看到,在没用锁的情况下,线程同时取到0并加1,结果都为1.

什么是锁?

  锁,跟门锁一样,他的作用不是为了锁定这个门,而是为了锁定门后的一方世界,也就是代码块。

  

技术分享图片
import threading
import time

lock = threading.RLock()
gl_num = 0
def show(arg):
    lock.acquire()
    global gl_num
    n = gl_num
    time.sleep(1)
    gl_num = n+1
    lock.release()
    print(gl_num)

for i in range(10):
    t = threading.Thread(target=show, args=(i,))
    t.start()

print (main thread stop)
加上锁
技术分享图片
main thread stop
1
2
3
4
5
6
7
8
9
10
结果

 

锁都有那些呢?

  两种:Lock(指令锁、RLock(可重入锁)。Lock属于全局,Rlock属于线程。

 

学习lock和Rlock区别前,我们要搞清楚什么事死锁。

死锁是:比如一辆车被两把锁锁住,你单单拿到一把锁的钥匙,你是开不了这个车的,这就是死锁。当然,这里是抽象的锁概念跟现实还有很大区别。

技术分享图片
import threading
import time

lock = threading.Lock()
gl_num = 0
def show(arg):
    lock.acquire()
    print(我只执行一次就被锁住了。,threading.current_thread().name)
    lock.acquire()
    time.sleep(1)
    print(threading.current_thread().name)
    lock.release()
    lock.release()


for i in range(10):
    t = threading.Thread(target=show, args=(i,))
    t.start()

print (main thread stop)
死锁
技术分享图片
我只执行一次就被锁住了。 Thread-1
main thread stop
结果

那么这死锁怎么解决?呵呵,用Rlock,这因为就是他们的区别了。

技术分享图片
import threading
import time

lock = threading.RLock()
gl_num = 0
def show(arg):
    lock.acquire()
    print(我只执行一次就被锁住了。,threading.current_thread().name)
    lock.acquire()
    time.sleep(1)
    print(threading.current_thread().name)
    lock.release()
    lock.release()


for i in range(10):
    t = threading.Thread(target=show, args=(i,))
    t.start()

print (main thread stop)
Rlock解决死锁,代码几乎不变
技术分享图片
我只执行一次就被锁住了。 Thread-1
main thread stop
Thread-1
我只执行一次就被锁住了。 Thread-2
Thread-2
我只执行一次就被锁住了。 Thread-3
Thread-3
我只执行一次就被锁住了。 Thread-4
Thread-4
我只执行一次就被锁住了。 Thread-5
Thread-5
我只执行一次就被锁住了。 Thread-6
Thread-6
我只执行一次就被锁住了。 Thread-7
Thread-7
我只执行一次就被锁住了。 Thread-8
Thread-8
我只执行一次就被锁住了。 Thread-9
Thread-9
我只执行一次就被锁住了。 Thread-10
Thread-10
结果

 总结

1、线程如果共用同一个数据(栈、队列),如果相互之间存在数据污染,那么就需要锁的来将操作公共数据的代码块锁起来。

2、锁的获取:lock = threading.Lock()或者lock = threading.RLock(),

3、lock跟RLock的区别,使用多把锁,那就需要Rlock来解决死锁问题。这里说的多把锁,是指一个锁多个嵌套。

 

以上是关于python锁的主要内容,如果未能解决你的问题,请参考以下文章

为啥基于锁的程序不能组成正确的线程安全片段?

LockSupport.java 中的 FIFO 互斥代码片段

读写锁 与 互斥锁

常用python日期日志获取内容循环的代码片段

python多线程

python 有用的Python代码片段