进程与线程:并发编程基础
摘要进程与线程是操作系统面试的必考点也是理解 AI 分布式训练和多线程数据加载的基础。本文从进程内存模型出发系统讲解线程同步机制锁、信号量、条件变量并通过 Python 代码展示多线程爬虫和生产者-消费者模型的实现。一、进程 vs 线程核心区别1.1 内存模型对比进程 B独立的地址空间进程 A代码段数据段堆栈 1栈 2共享内存图 1进程内存模型特性进程线程地址空间独立共享除栈外切换开销大需切换页表小通信方式IPC管道、共享内存、Socket直接读写共享变量崩溃影响不影响其他进程可能导致整个进程崩溃创建开销大小1.2 Python 的 GILPython 的GIL全局解释器锁意味着同一时刻只有一个线程执行 Python 字节码。但这不意味着多线程无用IO 密集型任务网络请求、文件读写多线程仍有收益CPU 密集型任务应使用多进程multiprocessing绕过 GIL。二、线程同步机制2.1 锁、信号量、条件变量 线程同步机制演示 包含锁、信号量、条件变量 importthreadingimporttimefromqueueimportQueuefromtypingimportListclassThreadSyncDemo:线程同步演示staticmethoddefdemo_lock(): 互斥锁演示 保护共享计数器的线程安全 counter0lockthreading.Lock()defincrement():nonlocalcounterfor_inrange(100000):withlock:# 获取锁counter1threads[threading.Thread(targetincrement)for_inrange(5)]fortinthreads:t.start()fortinthreads:t.join()print(f带锁计数器结果:{counter}(期望 500000))staticmethoddefdemo_semaphore(): 信号量演示 限制同时访问资源的线程数量 semaphorethreading.Semaphore(3)# 最多 3 个线程同时执行defworker(worker_id:int):withsemaphore:print(fWorker{worker_id}开始执行)time.sleep(1)print(fWorker{worker_id}执行完毕)threads[threading.Thread(targetworker,args(i,))foriinrange(6)]fortinthreads:t.start()fortinthreads:t.join()staticmethoddefproducer_consumer(): 生产者-消费者模型 使用条件变量实现线程间协调 queueQueue(maxsize10)defproducer():foriinrange(20):itemfitem_{i}queue.put(item)print(f生产:{item})time.sleep(0.1)defconsumer():for_inrange(20):itemqueue.get()print(f消费:{item})queue.task_done()time.sleep(0.2)pthreading.Thread(targetproducer)cthreading.Thread(targetconsumer)p.start()c.start()p.join()c.join()deftest_thread_sync():print(*60)print(线程同步测试)print(*60)demoThreadSyncDemo()print(\n【测试 1】互斥锁)demo.demo_lock()print(\n【测试 2】信号量)demo.demo_semaphore()print(\n【测试 3】生产者-消费者)demo.producer_consumer()print(\n*60)if__name____main__:test_thread_sync()代码 1线程同步机制三、AI 场景多进程数据加载 PyTorch DataLoader 风格的多进程数据加载 frommultiprocessingimportPool,QueueasMPQueueimporttimedefpreprocess_data(item_id:int)-dict:模拟数据预处理time.sleep(0.1)# 模拟耗时操作return{id:item_id,features:[item_id*iforiinrange(10)]}defparallel_data_loading(num_items:int100,num_workers:int4): 并行数据加载 使用多进程绕过 GIL加速 CPU 密集型预处理 starttime.time()withPool(num_workers)aspool:resultspool.map(preprocess_data,range(num_items))elapsedtime.time()-startprint(f加载{num_items}条数据{num_workers}个 Worker)print(f耗时:{elapsed:.2f}秒)print(f吞吐量:{num_items/elapsed:.1f}items/s)returnresultsdeftest_data_loading():print(\n并行数据加载测试:)parallel_data_loading(100,4)if__name____main__:test_data_loading()代码 2多进程数据加载四、面试高频问题Q1进程间通信有哪些方式答管道、消息队列、共享内存、信号量、Socket、信号。Q2死锁的四个必要条件答互斥、占有且等待、不可抢占、循环等待。破坏任一条件即可避免死锁。Q3Python 的多线程为什么不适合 CPU 密集型任务答GIL 限制同一时刻只有一个线程执行 Python 字节码多线程无法并行利用多核。五、总结核心要点进程是资源分配单位线程是调度单位线程同步是并发编程的核心难点锁粒度要细持有时间要短Python 中 IO 密集用线程CPU 密集用进程死锁预防优于检测设计时避免循环等待。本文基于 Coding Interview University 项目整理专注进程与线程专题。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2639235.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!