You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python多线程场景下如何保证job1始终先于job2执行?

线程固定优先级调度实现方案

问题现状

现有初始代码如下:

#threads
import threading
lock = threading.Lock()
t1 = threading.Thread(target=job1, args = (lock, )).start() 
t2 = threading.Thread(target=job2, args = (lock, )).start() 

两个线程启动后调度规则如下:

  • job1:每10秒递归重调度,单次执行耗时不足1秒,要求优先执行
  • job2:每60秒递归重调度,单次执行耗时4-5秒,优先级低于job1
    普通互斥锁threading.Lock采用平等竞争机制,无法保证调度触发时job1一定先拿到执行权,存在执行顺序随机的问题。

可选落地方案

按可靠性从高到低排序:

方案1:单线程轮询调度(零竞争,100%保序)

如果业务不强制要求两个任务跑在独立线程,这个方案成本最低、可靠性最高,从调度逻辑上彻底消除竞争:
整个调度逻辑跑在单线程循环里,每次轮询先检查高优先级job1的触发条件,执行完job1再检查低优先级job2的触发条件,从根上避免抢锁乱序问题。
示例代码:

import time

last_run_job1 = 0
last_run_job2 = 0
INTERVAL_JOB1 = 10
INTERVAL_JOB2 = 60

while True:
    current_ts = time.time()
    # 优先处理高优先级job1
    if current_ts - last_run_job1 >= INTERVAL_JOB1:
        job1()
        last_run_job1 = current_ts
    # job1处理完成后再检查job2
    if current_ts - last_run_job2 >= INTERVAL_JOB2:
        job2()
        last_run_job2 = current_ts
    # 降低空轮询CPU占用
    time.sleep(0.1)

该方案完全适配当前任务耗时场景:两个任务单次执行总耗时不超过6秒,远小于job1的10秒调度间隔,不会出现任务堆积。

方案2:基于条件变量的优先级锁(多线程场景适用)

如果必须保留两个独立线程的架构,替换普通互斥锁为条件变量+待执行计数机制,主动让低优先级任务在高优先级任务待执行时让出执行权:

  • 维护job1_pending计数器记录待执行的job1数量
  • job1触发时先计数+1,执行完成后计数-1并通知所有等待线程
  • job2执行前必须循环检查计数器,确认无待执行job1时才可以进入执行逻辑
    示例代码:
import threading
import time

cond = threading.Condition()
job1_pending = 0

def job1():
    global job1_pending
    # 标记job1待执行
    with cond:
        job1_pending += 1
    
    try:
        # 此处写入job1实际业务逻辑
        time.sleep(0.8) # 模拟单次执行不足1秒
    finally:
        # 执行完成后清除标记,通知等待线程
        with cond:
            job1_pending -= 1
            cond.notify_all()
    # 10秒递归重调度
    threading.Timer(10, job1).start()

def job2():
    global job1_pending
    # 等待所有待执行job1跑完再拿执行权
    with cond:
        while job1_pending > 0:
            cond.wait()
    
    try:
        # 此处写入job2实际业务逻辑
        time.sleep(4.5) # 模拟单次执行4-5秒
    finally:
        pass
    # 60秒递归重调度
    threading.Timer(60, job2).start()

# 启动任务
job1()
job2()

如果需要job2执行中途也能被job1抢占,可以把job2的长任务拆分为多个小执行步,每步执行前检查job1_pending状态,存在待执行job1时主动保存执行上下文并让出锁,等job1执行完成后再恢复job2的执行。

方案3:系统级线程优先级设置(不推荐,稳定性差)

可以通过操作系统接口调整两个线程的调度优先级,将job1绑定的线程优先级设置为高于job2的线程,但该方案存在明显缺陷:

  • 跨平台兼容性差:Windows、Linux、macOS的线程优先级设置接口不统一
  • 受Python GIL调度机制影响,无法100%保证用户态业务逻辑的执行顺序,仅适合非核心场景临时使用

避坑说明

普通threading.Lock、threading.RLock都不支持优先级调度,锁竞争时的获取顺序由操作系统调度决定,无法保证高优先级线程一定先拿到锁,不要用这类锁实现优先级控制。

内容的提问来源于stack exchange,提问作者Dasanudasa Krishna Balarama Da

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 22:01:19