一、什么是互斥锁
在多任务模式下,线程(任务)同时访问同一个变量或资源时,可能会产生竞争,导致数据混乱或错误。此时,需要对资源加锁,保证同一时刻只有一个线程在访问该资源。互斥锁(Mutex)就是一种保证同步的机制。
互斥锁的原理很简单:当某个线程获取到互斥锁时,其他线程就无法再获取到该锁,只有等待该锁释放后才能继续访问。
二、Python中常用的互斥锁
Python中有多种锁可供选择,常用的是threading模块中提供的Lock类和RLock类。
1. Lock类
Lock类是最简单的一种互斥锁,它拥有两个基本方法:acquire()和release(),分别是获取锁和释放锁的方法。当多个线程竞争一个 Lock 对象时,只能有一个线程会成功获取该锁。
import threading
lock = threading.Lock() # 创建一个 Lock 对象
def func():
lock.acquire() # 获取锁
# 访问共享资源
lock.release() # 释放锁
2. RLock类
RLock类是可重入锁,允许单个线程多次获得同一把锁,方便了锁的嵌套调用。 acquire() 和 release() 的使用方式同 Lock 类。
import threading
lock = threading.RLock() # 创建一个 RLock 对象
def func():
with lock:
# 访问共享资源,可以加锁嵌套
三、互斥锁的应用实例
下面以多线程下载图片为例,演示互斥锁的实际应用。
前提条件:已安装requests模块,有多张图片存储在urls.txt文件中。
import threading
import requests
lock = threading.Lock()
def download(url):
with lock:
filename = url.split('/')[-1]
r = requests.get(url)
with open(filename, 'wb') as f:
f.write(r.content)
print(filename + ' downloaded...')
def main():
urls = []
with open('urls.txt', 'r') as f:
urls = f.read().splitlines()
threads = []
for url in urls:
t = threading.Thread(target=download, args=(url,))
threads.append(t)
t.start()
for t in threads:
t.join()
print('All images downloaded successfully!')
if __name__ == '__main__':
main()
四、总结
互斥锁可以有效避免多线程访问资源时的竞争问题,保证了线程间的同步性。在Python中实现互斥锁主要是通过threading模块提供的 Lock 类和 RLock 类实现。
在实际应用中,我们可以将互斥锁用于多线程下载、多线程爬虫等需要访问同一资源的场合,确保多个线程之间的数据不发生冲突。