面试题答案
一键面试使用Python多线程加速数据预处理
- 导入必要库:
import threading import pandas as pd
- 定义数据处理函数:
def process_data(file_path): data = pd.read_csv(file_path) # 清洗数据,例如去除缺失值 data = data.dropna() # 转换数据,例如标准化 from sklearn.preprocessing import StandardScaler scaler = StandardScaler() data[['numeric_column1', 'numeric_column2']] = scaler.fit_transform(data[['numeric_column1', 'numeric_column2']]) return data
- 使用多线程:
file_paths = ['file1.csv', 'file2.csv', 'file3.csv'] threads = [] results = [] for file_path in file_paths: thread = threading.Thread(target=lambda: results.append(process_data(file_path))) threads.append(thread) thread.start() for thread in threads: thread.join() combined_data = pd.concat(results)
使用多线程可能遇到的问题及解决方法
- 全局解释器锁(GIL):
- 问题:Python中的GIL会限制多线程在CPU密集型任务中的并行性,使得同一时间只有一个线程能执行Python字节码,导致多线程在CPU密集型任务中加速效果不明显。
- 解决方法:对于CPU密集型任务,可以使用
multiprocessing
模块替代threading
模块,multiprocessing
利用多个进程并行执行任务,不受GIL限制。但进程间通信和资源管理比线程更复杂。
- 共享资源竞争:
- 问题:多个线程同时访问和修改共享数据时,可能导致数据不一致或错误。例如多个线程同时对一个计数器加1,可能会丢失一些计数。
- 解决方法:使用锁(
threading.Lock
)来保护共享资源。在访问共享资源前获取锁,访问结束后释放锁。
lock = threading.Lock() shared_variable = 0 def increment(): global shared_variable lock.acquire() try: shared_variable += 1 finally: lock.release()
- 死锁:
- 问题:当两个或多个线程相互等待对方释放锁时,会发生死锁,导致程序无法继续执行。
- 解决方法:避免嵌套锁,尽量按相同顺序获取锁;设置锁的超时时间,若在超时时间内未获取到锁则放弃,避免无限等待。
- 调试困难:
- 问题:多线程程序由于线程执行顺序的不确定性,调试起来比单线程程序更困难,错误可能难以复现。
- 解决方法:使用日志记录线程的执行状态和关键操作;使用调试工具,如
pdb
,结合日志信息逐步排查问题。