面试题答案
一键面试性能瓶颈原因分析
- 全局解释器锁(GIL):Python的GIL限制了同一时刻只有一个线程能执行Python字节码,对于CPU密集型任务,多线程无法利用多核优势,导致性能瓶颈。
- 线程切换开销:创建、销毁线程以及线程之间的切换都需要消耗系统资源,当线程数量过多时,这种开销会变得显著,影响整体性能。
- 资源竞争:多个线程同时访问共享资源(如文件、数据库连接等)时,可能会因为锁竞争导致线程阻塞,降低执行效率。
优化策略及代码示例
- 使用多进程替代多线程(针对CPU密集型任务)
- 实现方式:
import multiprocessing
def cpu_bound_task(n):
return sum(i * i for i in range(n))
if __name__ == '__main__':
numbers = [10000000, 20000000, 30000000]
with multiprocessing.Pool(processes=multiprocessing.cpu_count()) as pool:
results = pool.map(cpu_bound_task, numbers)
print(results)
- **预期效果**:多进程可以充分利用多核CPU的优势,提高CPU密集型任务的执行效率。由于每个进程都有自己独立的Python解释器和内存空间,不存在GIL的限制。
2. 线程池(减少线程创建和销毁开销) - 实现方式:
import concurrent.futures
import threading
def io_bound_task():
# 模拟I/O操作,如读取文件、网络请求等
import time
time.sleep(1)
return threading.current_thread().name
if __name__ == '__main__':
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
results = list(executor.map(io_bound_task, range(20)))
print(results)
- **预期效果**:线程池预先创建一定数量的线程,任务提交到线程池后,可复用这些线程,减少线程创建和销毁的开销,提高I/O密集型任务的处理效率。
3. 优化共享资源访问(减少锁竞争) - 实现方式:
import threading
import queue
class SharedResource:
def __init__(self):
self.data = 0
self.lock = threading.Lock()
def update_resource(resource, q):
while not q.empty():
value = q.get()
with resource.lock:
resource.data += value
q.task_done()
if __name__ == '__main__':
resource = SharedResource()
work_queue = queue.Queue()
for i in range(100):
work_queue.put(i)
num_threads = 5
threads = []
for _ in range(num_threads):
t = threading.Thread(target=update_resource, args=(resource, work_queue))
t.start()
threads.append(t)
for t in threads:
t.join()
print(resource.data)
- **预期效果**:通过使用队列来管理对共享资源的访问请求,线程从队列中获取任务,减少了直接的锁竞争。在更新共享资源时,使用`with`语句确保锁的正确获取和释放,提高多线程环境下对共享资源操作的效率。