MST

星途 面试题库

面试题:Python函数内部修改列表在多线程环境下的注意事项

在Python的多线程编程中,有一个全局列表`shared_list = []`,定义两个线程函数`thread_func1`和`thread_func2`,这两个函数都会对`shared_list`进行添加元素操作。请编写代码实现这个场景,并说明在函数内部修改列表时,在多线程环境下可能会遇到什么问题,如何解决这些问题(比如使用锁机制)?请详细阐述锁机制在这种场景下的工作原理和实现方式。
35.8万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试
import threading

shared_list = []
lock = threading.Lock()


def thread_func1():
    for i in range(5):
        with lock:
            shared_list.append(i)


def thread_func2():
    for i in range(5, 10):
        with lock:
            shared_list.append(i)


if __name__ == "__main__":
    t1 = threading.Thread(target=thread_func1)
    t2 = threading.Thread(target=thread_func2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(shared_list)

多线程环境下可能遇到的问题

在多线程环境下,当多个线程同时对shared_list进行添加元素操作时,可能会出现数据竞争问题。由于线程调度的不确定性,多个线程可能会同时访问和修改shared_list,导致最终的结果不符合预期。例如,两个线程同时获取到shared_list的当前长度,然后都在这个长度位置添加元素,就会造成数据覆盖或者丢失。

锁机制的工作原理

锁机制是一种同步原语,用于确保在同一时刻只有一个线程可以访问共享资源。在Python中,threading.Lock类提供了锁的实现。当一个线程获取到锁时,其他线程必须等待锁被释放后才能获取锁并访问共享资源。这样就保证了在同一时间只有一个线程可以对shared_list进行操作,避免了数据竞争。

锁机制的实现方式

  1. 创建锁对象:使用threading.Lock()创建一个锁对象,例如lock = threading.Lock()
  2. 获取锁:在需要保护共享资源的代码段前调用lock.acquire()方法获取锁。如果锁当前可用,线程将获取锁并继续执行;如果锁已被其他线程持有,当前线程将被阻塞,直到锁被释放。
  3. 释放锁:在对共享资源操作完成后,调用lock.release()方法释放锁,以便其他线程可以获取锁并访问共享资源。在Python中,使用with语句可以更方便地管理锁的获取和释放,如上述代码中的with lock:语句块,它会在进入代码块时自动获取锁,在离开代码块时自动释放锁。