亲宝软件园·资讯

展开

Python线程锁

LiveEveryDay 人气:0

前言

当有多个线程,且它们同时访问同一资源时,需要考虑如何避免线程冲突。解决办法是使用线程锁。锁由Python的threading模块提供,并且它最多被一个线程所持有。当一个线程试图获取一个已经锁在资源上的锁时,该线程通常会暂停运行,直到这个锁被释放。看看下面的不具备锁功能的例子:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author: LiveEveryDay
 
 
import threading
 
total = 0
 
 
def update_total(amount):
    global total
    total += amount
    print(total)
 
 
if __name__ == '__main__':
    for i in range(10):
        my_thread = threading.Thread(target=update_total, args=(5,))
        my_thread.start()
 
''' ------ Running Results ------
510
15
20
25
30
3540
45
50
'''

如果往以上代码添加 time.sleep 函数并给出不同长度的时间,可能会让这个例子更有意思。无论如何,这里的问题是,一个线程可能已经调用 update_total 函数并且还没有更新完成,此时另一个线程也有可能调用它并且尝试更新内容。根据操作执行顺序的不同,该值可能只被增加一次。

给它添加锁后:

方式一:使用try/finally,确保锁肯定会被释放。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author: LiveEveryDay
 
 
import threading
 
total = 0
lock = threading.Lock()
 
 
def update_total(amount):
    global total
    lock.acquire()
    try:
        total += amount
    finally:
        print(total)
        lock.release()
 
 
if __name__ == '__main__':
    for i in range(10):
        my_thread = threading.Thread(target=update_total, args=(5,))
        my_thread.start()
 
''' ------ Running Results ------
5
10
15
20
25
30
35
40
45
50
'''

如上,在我们做任何处理之前就获取锁。然后尝试更新 total 的值,最后打印出 total 的当前值并释放锁。

方式二:with语句避免使用try/finally。

事实上,我们可以使用 Python 的 with 语句避免使用 try/finally 这种较为繁琐的语句:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author: LiveEveryDay
 
 
import threading
 
total = 0
lock = threading.Lock()
 
 
def update_total(amount):
    global total
    with lock:
        total += amount
        print(total)
 
 
if __name__ == '__main__':
    for i in range(10):
        my_thread = threading.Thread(target=update_total, args=(5,))
        my_thread.start()
 
''' ------ Running Results ------
5
10
15
20
25
30
35
40
45
50
'''

总结

加载全部内容

相关教程
猜你喜欢
用户评论