多线程操作非共享变量时:可共用同一锁还是需用多锁?
线程锁使用疑问解答
核心问题解答
能否为操作独立变量的线程共用同一把锁?
可以,但完全没必要——甚至会拖慢程序性能。
你的第一个示例里,两个线程分别操作完全独立的var1和var2,它们的操作本来不会互相干扰,不需要互斥逻辑。但如果共用同一把Lock,两个线程会被强制串行执行:第一个线程拿到锁修改变量时,第二个线程必须等锁释放才能执行,白白浪费了多线程并行的优势,还额外增加了锁竞争的开销。
哪种实现方式更优?
显然第二个示例使用两把独立的Lock是更好的选择。
因为两个变量属于完全独立的共享资源,为它们分配专属锁,既能保证单个变量操作的线程安全,又能让两个线程并行执行,最大化利用多线程的性能优势。
补充说明:你的示例代码中
var = 1是局部变量赋值,不会修改外部的var1/var2(因为列表是可变对象,但这里直接覆盖了函数内的引用)。实际业务中如果要修改外部变量的内容(比如var.append(1)),才需要锁来保护操作的原子性。
多把锁的适用场景
- 独立资源并行处理:当多个线程操作完全独立的共享资源时,用多把锁可以让各线程同时执行,避免不必要的串行等待,提升整体运行效率。
- 细粒度锁优化性能:面对复杂数据结构(如拆分的哈希表、分块存储的数据集),不同部分的修改互不影响,给每个部分分配独立的锁,能在保证线程安全的同时,大幅减少锁竞争概率,提升并发处理能力。
- 降低死锁风险(需谨慎设计):在嵌套锁的场景中,合理拆分锁的粒度,配合严格的锁获取顺序,可以降低死锁的发生概率。
修正后的代码示例
共用单锁(不推荐)
from threading import Thread, Lock from time import sleep def task(lock, var): with lock: # 实际业务中修改可变对象内容时才需要锁 var.append(1) sleep(5) lock = Lock() var1 = [] var2 = [] Thread(target=task, args=(lock, var1)).start() Thread(target=task, args=(lock, var2)).start()
使用独立锁(推荐)
from threading import Thread, Lock from time import sleep def task(lock, var): with lock: var.append(1) sleep(5) lock1 = Lock() lock2 = Lock() var1 = [] var2 = [] Thread(target=task, args=(lock1, var1)).start() Thread(target=task, args=(lock2, var2)).start()
内容的提问来源于stack exchange,提问作者alec_djinn
相关产品推荐
相关产品推荐

