一、python多线程崩溃
1)所以在python里线程不要盲目用, 也不要滥用。 但是线程不安全是事实。如果仅仅是做几个后台任务,则可以考虑使用守护线程做。如果需要做一些危险操作,可能会崩溃的,就用子进程去做。 如果需要高度稳定性,同时并发数又不高的服务。则强烈建议用多进程的multiprocessing模块实现。在linux或者是unix里,进程的使用代价没有windows高。还是可以接受的。
2)线程出错:在使用Python的ThreadPoolExecutor进行多线程任务处理时,可能会在任务执行过程中出现异常、崩溃或未能返回期望结果的情况。资源耗尽问题:无界队列导致OOM:使用无界队列(如linkedBlockingQueue)时,当任务耗时较长,可能会导致大量新任务在队列中堆积,最终导致OOM。
3)使用多进程代替多线程:Python的multiprocessing模块允许创建独立的进程,每个进程有自己的Python解释器和内存空间,因此不受GIL的影响。这种方法可以充分利用多核处理器的并行处理能力。使用异步编程:对于I/O密集型任务,可以使用异步I/O框架(如asyncio)来提高效率。
二、python多线程的问题如何处理
1) 多线程并发操作冲突(PLC通信场景)在使用Python-Snap7库与西门子PLC通信时,若多线程同时调用read_area等读写方法,可能因未正确处理同步机制触发";Job pending";异常。此问题通常源于线程间对PLC资源的竞争访问,导致操作挂起。
2)线程Event:用于线程间的通知。线程锁Lock:用于保护共享资源,防止多个线程同时访问。Python线程的GIL问题 GIL(全局解释器锁)导致Python解释器同一时刻只能解释一个线程,降低了线程的执行效率。
3)当多个线程操作同一份数据时,可能会出现数据错乱的问题。使用互斥锁(Lock)可以确保同一时间只有一个线程访问共享资源,避免数据竞争。GIL(全局解释器锁)GIL是Cpython解释器中的一个机制,它确保同一时间只有一个线程执行Python字节码。GIL限制了Python多线程在多核CPU上的并行执行能力。
4)对于多进程场景,可以使用`multiprocessing`模块中的`terminate`方法来强制终止子进程。这种方法提供了与多线程类似的API,但通过使用子进程而非线程有效地绕过了全局解释器锁,因此能够充分利用给定机器上的多个处理器。
三、threadpoolexecutor会出现的问题
1)上下文管理协议相当于隐性地省略了 threadPool.shutdown(wait=True) ,程序正常执行完成或出现异常中断的时候,就会调用 __exit__() 方法,接下来进行异常中止的基础。适用于 Django 等 WEB 应用框架,本身自带多线程,修改全局变量简单,但要注意线程安全。
2)异常掩盖问题 原因:ThreadPoolExecutor通过Future对象包装任务,工作线程抛出的异常会被封装在Future中,若未主动检查,异常会静默失败。
3)任务代码问题 死循环任务:线程池中可能存在提交了死循环的任务,导致线程无法正常结束。任务处理耗时过长:任务逻辑复杂或外部依赖(如数据库、网络)响应慢,导致线程长时间占用CPU。
4)ThreadPoolExecutor 的饱和策略(拒绝策略)主要有四种标准实现:AbortPolicy、CallerRunsPolicy、DiscardPolicy 和 DiscardOldestPolicy。它们决定了当线程池无法处理新提交的任务时,如何应对。以下是具体说明:AbortPolicy(默认策略):当任务被拒绝时,直接抛出 RejectedExecutionException 运行时异常。
5)内存不足、资源不可用等极端情况可能导致任务提交失败。解决策略 配置诊断性 RejectedExecutionHandler问题:静默处理的 RejectedExecutionHandler 会隐藏任务被拒绝的信息。改进方案:抛出异常或记录日志,暴露线程池状态(如是否关闭、活跃线程数、队列大小)。
四、Python进阶为什么GIL让多线程变得如此鸡肋
1)Python并不是没有多线程,但Python的多线程在某些情况下表现不佳,主要原因如下: 全局解释器锁(GIL)的存在:限制并行执行:Python中的GIL确保任何时候只有一个Python线程能够执行Python字节码。
2)当CPU核心从单核时代步入多核,Python为了充分利用多核性能,引入了多线程。GIL的存在却在无形中降低了多线程的效率。
3)GIL的存在原因:GIL的设计初衷是为了简化Python解释器的内存管理,尤其是引用计数机制。每个Python对象通过引用计数管理内存,当计数归零时对象被回收。在多线程环境下,若没有GIL,对引用计数的修改需加锁保护,否则会导致数据竞争和内存错误。
4)GIL的存在主要是为了解决多线程之间数据完整性和状态同步的问题。以Python中对象的管理为例,对象通过引用计数器进行管理,当引用数为0时释放对象。如果没有GIL,多个线程同时修改引用计数器可能导致数据不一致或错误。举例说明:假设线程A和线程B都引用了对象obj,obj.ref_num = 2。




