当前位置:首页>python>Python 中的锁(Locks)详解

Python 中的锁(Locks)详解

  • 2026-08-21 06:07:39
Python 中的锁(Locks)详解

Python 中的锁(Locks)详解



1. 为什么需要锁

多线程/多进程环境下,多个执行单元同时访问共享资源会导致竞态条件(Race Condition)

▲ 两个线程同时对 counter+=1,因非原子操作导致结果错误(丢失一次更新)
import threadingcounter = 0def increment():    global counter    for _ in range(100000):        counter += 1  # 非原子操作:读→加→写,三步之间可能被切换threads = [threading.Thread(target=increment) for _ in range(10)]for t in threads:    t.start()for t in threads:    t.join()print(counter)  # 期望 1000000,实际结果不确定(每次都不同)

根本原因:counter += 1 在字节码层面是 3 条指令,线程可能在任意两条之间被切换。

锁通过**互斥(Mutual Exclusion)**保证同一时刻只有一个执行单元访问临界区。


2. threading 模块中的锁

2.1 Lock(互斥锁)

最基本的锁,两种状态:锁定未锁定

import threadinglock = threading.Lock()counter = 0def increment():    global counter    for _ in range(100000):        lock.acquire()          # 获取锁(阻塞直到成功)        try:            counter += 1        # 临界区        finally:            lock.release()      # 释放锁(必须在 finally 中)# 推荐:使用上下文管理器def increment_safe():    global counter    for _ in range(100000):        with lock:              # 自动 acquire + release            counter += 1

核心 API

方法说明
acquire(blocking=True, timeout=-1)获取锁。blocking=False 时非阻塞,立即返回 True/False
release()释放锁。非持有者调用会抛 RuntimeError
locked()返回锁是否被持有

阻塞 vs 非阻塞

if lock.acquire(blocking=False):    # 尝试获取,拿不到立即返回 False    try:        do_something()    finally:        lock.release()else:    print("锁被占用,执行其他逻辑")# 带超时if lock.acquire(timeout=2.0):       # 最多等 2 秒    try:        do_something()    finally:        lock.release()

2.2 RLock(可重入锁)

同一个线程可以多次 acquire,不会死锁。需要等次数的 release 才能真正解锁。

import threadingrlock = threading.RLock()def recursive_func(n):    with rlock:        if n <= 0:            return        print(f"深度 {n},锁被同一线程再次获取")        recursive_func(n - 1)   # 重入!Lock 会在这里死锁recursive_func(3)

Lock vs RLock

特性LockRLock
同一线程重入死锁允许
持有者追踪不追踪追踪持有线程和获取次数
释放要求任意线程可释放(不推荐跨线程)必须由持有线程释放
性能更快略慢(有额外记录开销)

使用建议:不确定函数调用链中有没有重入需求时,用 RLock;明确不会重入、追求极致性能时用 Lock。


2.3 Semaphore(信号量)

允许最多 N 个线程同时访问资源(Lock 是 N=1 的特殊信号量)。

import threadingimport timeimport random# 最多 3 个线程同时访问数据库连接池db_semaphore = threading.Semaphore(3)def query_database(thread_id):    with db_semaphore:        print(f"线程 {thread_id} 获取连接,当前并发数未知")        time.sleep(random.uniform(0.51.5))  # 模拟查询        print(f"线程 {thread_id} 释放连接")threads = [threading.Thread(target=query_database, args=(i,)) for i in range(10)]for t in threads:    t.start()for t in threads:    t.join()

典型场景

  • 数据库连接池(限制最大连接数)
  • API 限流(控制并发请求数)
  • 文件句柄限制

2.4 BoundedSemaphore

与 Semaphore 的唯一区别:release() 次数不能超过 acquire() 次数,否则抛 ValueError。

sem = threading.Semaphore(3)sem.release()# 不报错,计数器变成 4(超出初始值)bsem = threading.BoundedSemaphore(3)bsem.release()# ValueError: Semaphore released too many times

意义:捕捉"释放次数多于获取次数"的 bug(这通常意味着代码逻辑错误)。


2.5 Condition(条件变量)

比锁更高级的同步原语:一个线程等待某个条件成立,另一个线程通知条件已满足。

import threadingimport timecondition = threading.Condition()items = []def consumer():    with condition:        while not items:                    # 用 while 而非 if 防虚假唤醒            print("消费者:队列空,等待...")            condition.wait()                # 释放锁 + 阻塞,被 notify 后重获锁        item = items.pop(0)        print(f"消费者:取出 {item}")def producer():    time.sleep(1)    with condition:        items.append("data")        print("生产者:放入 data")        condition.notify()                  # 唤醒 1 个等待线程        # condition.notify_all()            # 唤醒所有等待线程threading.Thread(target=consumer).start()threading.Thread(target=producer).start()

关键点

  • wait() 会原子性地释放锁并阻塞,被唤醒后重新获取锁再返回

  • 条件检查用 while 而非 if:防止虚假唤醒(spurious wakeup)

  • notify(n=1) 唤醒 n 个等待线程;notify_all() 唤醒全部

生产者-消费者模式

import threadingimport randomcond = threading.Condition()queue = []MAX_SIZE = 5def producer():    for i in range(10):        with cond:            while len(queue) >= MAX_SIZE:                cond.wait()                    # 队列满,等待消费者消费            queue.append(i)            print(f"生产 {i},队列: {queue}")            cond.notify_all()                  # 通知所有消费者def consumer(name):    while True:        with cond:            while not queue:                cond.wait()                    # 队列空,等待生产者            item = queue.pop(0)            print(f"{name} 消费 {item},队列: {queue}")            cond.notify_all()threading.Thread(target=producer, daemon=True).start()threading.Thread(target=consumer, args=("C1",), daemon=True).start()threading.Thread(target=consumer, args=("C2",), daemon=True).start()

2.6 Event(事件)

最简单的线程间通信机制:一个线程发信号,其他线程等待信号。

import threadingimport timeevent = threading.Event()  # 初始为 False(未设置)def waiter():    print("等待事件...")    event.wait()            # 阻塞直到 event.is_set() == True    print("事件已触发,继续执行")def setter():    time.sleep(2)    print("设置事件")    event.set()             # 设为 True,唤醒所有等待线程threading.Thread(target=waiter).start()threading.Thread(target=setter).start()

核心 API

方法说明
set()将内部标志设为 True,唤醒所有等待线程
clear()将内部标志重置为 False
wait(timeout=None)阻塞直到标志为 True,可设置超时
is_set()查询当前标志状态

Event 是一次性信号弹,Condition 是可以反复使用的精密开关。


2.7 Barrier(屏障)

让 N 个线程在某个点互相等待,全部到达后才能继续。

import threadingimport timeimport randombarrier = threading.Barrier(3)  # 3 个线程到齐才放行def worker(thread_id):    print(f"线程 {thread_id} 阶段1 开始")    time.sleep(random.uniform(0.52))    print(f"线程 {thread_id} 阶段1 完成,等待其他线程...")    barrier.wait()              # 阻塞,凑齐 3 个才继续    print(f"线程 {thread_id} 阶段2 开始")threads = [threading.Thread(target=worker, args=(i,)) for i in range(3)]for t in threads:    t.start()

适合场景

  • 并行计算的阶段同步(MapReduce)
  • 多线程初始化完成后统一开始
  • 测试中等待所有线程就绪

3. multiprocessing 模块中的锁

多进程共享内存时也需要同步。API 与 threading 几乎一致。

import multiprocessing# 与 threading 对应关系:# threading.Lock()          → multiprocessing.Lock()# threading.RLock()         → multiprocessing.RLock()# threading.Semaphore()     → multiprocessing.Semaphore()# threading.Event()         → multiprocessing.Event()# threading.Condition()     → multiprocessing.Condition()# threading.Barrier()       → multiprocessing.Barrier()lock = multiprocessing.Lock()counter = multiprocessing.Value('i'0)def increment():    for _ in range(100000):        with lock:            counter.value += 1processes = [multiprocessing.Process(target=increment) for _ inrange(4)]for p in processes:    p.start()for p in processes:    p.join()print(counter.value)  # 400000,正确

与 threading 的关键区别

  • multiprocessing 锁存在于共享内存/内核对象中,跨进程可见

  • 必须通过 multiprocessing.Manager 或在主进程创建后传给子进程

  • 不能在 Pool.map 等不能 pickle 的上下文中直接使用(需用 Manager 或 initializer

  • 性能开销比 threading 锁大(涉及内核态/用户态切换)

Manager 共享锁

import multiprocessingdef worker(lock, shared_list):    with lock:        shared_list.append(multiprocessing.current_process().name)if __name__ == '__main__':    with multiprocessing.Manager() as manager:        lock = manager.Lock()        shared_list = manager.list()        jobs = [multiprocessing.Process(target=worker, args=(lock, shared_list)) for _ inrange(5)]        for j in jobs:            j.start()        for j in jobs:            j.join()        print(list(shared_list))

4. asyncio 模块中的锁

asyncio 锁用于协程之间的同步,必须在 async def 函数内使用 await。它们不能跨线程或跨进程使用。

import asyncio# 对应关系(asyncio 是 awaitable 版本):# threading.Lock → asyncio.Lock# threading.RLock → (asyncio 无 RLock,不需要:单线程事件循环天然不重入死锁)# threading.Semaphore → asyncio.Semaphore# threading.Event → asyncio.Event# threading.Condition → asyncio.Condition# threading.Barrier → asyncio.Barrier(3.9+)# 无对应 → asyncio.BoundedSemaphore

4.1 asyncio.Lock

import asynciolock = asyncio.Lock()counter = 0async def increment():    global counter    for _ in range(1000):        async with lock:           # await lock.acquire() + lock.release()            counter += 1async def main():    await asyncio.gather(*[increment(for _ in range(10)])    print(counter)  # 10000asyncio.run(main())

关键区别

  • async with lock 不会阻塞整个线程,只挂起当前协程
  • 不能从同步代码中调用

4.2 asyncio.Semaphore(协程并发限制)

import asynciosem = asyncio.Semaphore(5)  # 最多 5 个协程并发请求async def fetch(url):    async with sem:        print(f"请求 {url}(获取信号量)")        await asyncio.sleep(1)  # 模拟 I/O        print(f"请求 {url} 完成(释放信号量)")        return f"result of {url}"async def main():    urls = [f"http://example.com/{i}" for i in range(20)]    results = await asyncio.gather(*[fetch(url) for url in urls])

这也是最简单的异步限流器

4.4 为什么 asyncio 没有 RLock

单线程事件循环中,协程之间是协作式切换(遇到 await 才可能切换),不存在同一个协程重入同一把锁的场景。如果需要"协程重入",通常说明设计有问题。


5. 死锁与避免策略

    5.1 死锁的四个必要条件

    1. 互斥:资源不能被共享使用

    2. 持有并等待:持有锁的线程可以等待其他锁

    3. 不可抢占:锁只能由持有者释放

    4. 循环等待:线程之间形成锁的环形依赖链

      5.2 典型死锁场景

      import threadinglock_a = threading.Lock()lock_b = threading.Lock()def thread1():    with lock_a:        time.sleep(0.1)         # 模拟处理        with lock_b:            # 等待 lock_b(被 thread2 持有)            print("线程1 获取两把锁")def thread2():    with lock_b:        time.sleep(0.1)        with lock_a:            # 等待 lock_a(被 thread1 持有)            print("线程2 获取两把锁")threading.Thread(target=thread1).start()threading.Thread(target=thread2).start()# 两个线程互相等待 → 死锁

      5.3 避免策略

      ① 统一锁的获取顺序(最有效)

      # 始终按 lock_a → lock_b 的顺序获取def safe():    with lock_a:        with lock_b:            do_work()

      ② 使用超时 + 回退

      def try_acquire():    while True:        lock_a.acquire()        if lock_b.acquire(timeout=0.5):            try:                do_work()                return            finally:                lock_b.release()                lock_a.release()        else:            lock_a.release()     # 回退,避免持有并等待            time.sleep(0.1)      # 随机退避更好

      ③ 使用 RLock 避免重入死锁(只解决重入问题)

      ④ 减少锁的粒度

      # 不好:大锁with big_lock:    read_from_db()    process()    write_to_file()# 更好:锁只保护必要的临界区data = read_from_db()result = process(data)with data_lock:    shared_cache.update(result)

      ⑤ 使用threading.local()消除共享(如果可能)

      import threadinglocal_data = threading.local()def worker():    local_data.counter = 0  # 每个线程独立副本,无需锁    for _ inrange(1000):        local_data.counter += 1

      6. 锁的进阶话题

      6.1 GIL(全局解释器锁)详解与实战案例

      GIL(Global Interpreter Lock)是CPython 解释器中的一个互斥锁,它保证同一时刻只有一个线程在执行 Python 字节码

      注意:GIL 是 CPython 的实现特性,Jython(Java 实现)和 IronPython(.NET 实现)没有 GIL。

      6.1.2 实战案例一:CPU 密集型——为什么多线程反而更慢?

      以下是一个完整的对比实验:

      import threadingimport multiprocessingimport time# ============================================# 案例:计算 0 到 N 的平方和(纯 CPU 计算)# ============================================def cpu_bound_task(n): ”””纯 CPU 密集型任务:无任何 I/O 操作””” total = 0 for i in range(n): total += i * i return totaldef run_single_thread(n): ”””单线程执行””” start = time.time() cpu_bound_task(n) return time.time() - startdef run_multi_thread(n, num_threads): ”””多线程执行——将任务拆分为多个子任务””” start = time.time() threads = [] chunk = n // num_threads for _ in range(num_threads): t = threading.Thread(target=cpu_bound_task, args=(chunk,)) threads.append(t) t.start() for t in threads: t.join() return time.time() - startdef run_multi_process(n, num_processes): ”””多进程执行””” start = time.time() processes = [] chunk = n // num_processes for _ in range(num_processes): p = multiprocessing.Process(target=cpu_bound_task, args=(chunk,)) processes.append(p) p.start() for p in processes: p.join() return time.time() - startif __name__ == '__main__': N = 50_000_000# 5 千万次循环 t1 = run_single_thread(N * 4) print(f”单线程耗时: {t1:.2f}s”) t2 = run_multi_thread(N * 44) print(f”4 线程耗时: {t2:.2f}s(线程数倍反而更慢)”) t3 = run_multi_process(N * 44) print(f”4 进程耗时: {t3:.2f}s(接近线性加速)”)# ============================================# 实际运行结果示例(4 核 CPU):# 单线程耗时: 10.21s# 4 线程耗时: 13.87s(因为 GIL 竞争,比单线程还慢!)# 4 进程耗时: 3.15s(每个进程有独立 GIL,真正并行)# ============================================

      现象分析

      单线程执行流程:  [====计算====]                           → 10.21s4 线程执行流程(受 GIL 限制):  线程1: [算][等][算][等][算][等][算][等]  线程2: [等][算][等][算][等][算][等][算]  线程3: [等][算][等][算][等][算][等][算]  线程4: [等][算][等][算][等][算][等][算]  每个"等"都是 GIL 竞争开销,还有线程切换的上下文成本  → 总耗时 ≈ 单线程 + 线程切换 + GIL 争夺开销4 进程执行流程(独立 GIL):  进程1: [=========计算=========]  进程2: [=========计算=========]  进程3: [=========计算=========]  进程4: [=========计算=========]  → 总耗时 ≈ 单线程 / 4(真并行)

      6.1.3 实战案例二:I/O 密集型——多线程有效

      import threadingimport multiprocessingimport time# ============================================# I/O 密集型任务:模拟网络请求# ============================================def io_bound_task(task_id):    """模拟 I/O 操作(sleep 代表等待网络/磁盘)"""    time.sleep(1)                # 模拟 1 秒 I/O 等待    return f"task {task_id} done"def run_sequential(num_tasks):    """串行执行"""    start = time.time()    for i in range(num_tasks):        io_bound_task(i)    return time.time() - startdef run_multi_thread(num_tasks):    """多线程执行"""    start = time.time()    threads = [threading.Thread(target=io_bound_task, args=(i,))               for i in range(num_tasks)]    for t in threads:        t.start()    for t in threads:        t.join()    return time.time() - startdef run_multi_process(num_tasks):    """多进程执行"""    start = time.time()    processes = [multiprocessing.Process(target=io_bound_task, args=(i,))                 for i in range(num_tasks)]    for p in processes:        p.start()    for p in processes:        p.join()    return time.time() - startif __name__ == '__main__':    N = 10    t1 = run_sequential(N)    print(f"串行执行 {N} 个任务:    {t1:.2f}s")    t2 = run_multi_thread(N)    print(f"多线程执行 {N} 个任务:  {t2:.2f}s")    t3 = run_multi_process(N)    print(f"多进程执行 {N} 个任务:  {t3:.2f}s")# ============================================# 实际运行结果:# 串行执行 10 个任务:    10.01s# 多线程执行 10 个任务:   1.01s(近 10 倍提速!)# 多进程执行 10 个任务:   1.52s(有效但进程创建有额外开销)# ============================================

      原理

      I/O 密集 - 多线程: 线程1: [算][----等待 I/O----][算] 线程2: [算][----等待 I/O----][算] 线程3: [算][----等待 I/O----][算] 关键:当线程执行 time.sleep() / socket.recv() 等 I/O 操作时, GIL 被自动释放,其他线程可以获取 GIL 继续执行 → I/O 等待期间 CPU 不空闲,多线程非常有效

      6.1.4 GIL 释放的时机

      GIL 在以下情况下会释放:

      释放时机说明
      当前线程执行 I/O 操作time.sleep()socket.recv()、文件读写等
      解释器轮转CPython 3.2+ 每执行约 15ms 或一定字节码指令后主动释放
      显式释放在 C 扩展中调用 Py_BEGIN_ALLOW_THREADS
      import sys# 查看 GIL 切换间隔(Python 3.2+)print(sys.getswitchinterval())# 默认 0.005 秒 = 5ms

      6.1.5 案例三:GIL 不保证线程安全

      import threading# ================================================# 关键误解:GIL 不保证你的代码线程安全!# ================================================counter = 0def flawed_increment():    """    以为 GIL 保护了 counter += 1 吗?    错!dis 模块揭示真相:    """    global counter    for _ in range(100_000):        counter += 1        # 字节码层面(用 dis.dis(flawed_increment) 查看):        # LOAD_GLOBAL     counter    ← 可能在此被切换        # LOAD_CONST      1        # INPLACE_ADD        # STORE_GLOBAL    counter    ← 可能在此被切换        # 四条指令之间 GIL 可能被释放 → 竞态条件!# 验证:多线程执行 flawed_incrementdef test_flawed():    global counter    counter = 0    threads = [threading.Thread(target=flawed_increment) for _ in range(10)]    for t in threads:        t.start()    for t in threads:        t.join()    print(f"期望 1,000,000,实际 {counter}")    # 每次结果不同,如 732491、891023...test_flawed()# ================================================# 正确做法:用自己的锁保护# ================================================lock = threading.Lock()counter2 = 0def safe_increment():    global counter2    for _ in range(100_000):        with lock:            counter2 += 1def test_safe():    global counter2    counter2 = 0    threads = [threading.Thread(target=safe_increment) for _ in range(10)]    for t in threads:        t.start()    for t in threads:        t.join()    print(f"期望 1,000,000,实际 {counter2}")    # 结果:1,000,000 ✓test_safe()

      6.1.6 实战决策:什么时候用什么?

      你的任务类型? │ ├── CPU 密集(计算、图像处理、加密...) │ └── multiprocessing(绕过 GIL,用多核) │ ├── I/O 密集(网络请求、文件读写、数据库...) │ └── threading 或 asyncio(GIL 会在 I/O 时释放,多线程有效) │ └── 混合型 └── 多进程 + 每进程内用线程池/协程一句话总结: 多线程在 Python 里是用来”等”的(等 I/O),不是用来”算”的(算 CPU)

      6.1.7 GIL 的未来

      Python 3.13 开始引入了 PEP 703 — 可选 GIL(free-threaded 模式),允许在无 GIL 状态下运行。目前处于实验阶段,是 Python 社区正在推进的重要方向。

      方面GIL(全局解释器锁)threading.Lock
      级别解释器级别,自动管理用户代码级别,手动管理
      保护对象CPython 内部数据结构用户定义的共享变量
      能否释放每执行 N 条字节码或遇到 I/O 自动释放手动 release()
      影响同一时刻只有一个线程执行 Python 字节码同一时刻只有一个线程进入临界区

      关键结论GIL 不保证你代码的原子性,Python 层面的非原子操作仍然需要 Lock。

      # counter += 1 虽然每条指令都持有 GIL,但可能在不同指令之间释放 GIL# 所以仍然需要 threading.Lock

      6.2 锁的粒度权衡

      细粒度锁优点:并发高细粒度锁缺点:代码复杂、死锁风险高粗粒度锁优点:简单安全粗粒度锁缺点:并发低

      建议:先用粗粒度锁保证正确性,profile 后发现瓶颈再细化。

      6.3 读写锁(RWLock)

      Python 标准库没有内置读写锁,但可以自己实现或用第三方库。读写锁允许多个读者同时访问,写者独占访问。

      import threadingclass ReadWriteLock:    def __init__(self):        self._readers = 0        self._writers = 0        self._condition = threading.Condition()    def acquire_read(self):        with self._condition:            while self._writers > 0:                self._condition.wait()            self._readers += 1    def release_read(self):        with self._condition:            self._readers -= 1            if self._readers == 0:                self._condition.notify_all()    def acquire_write(self):        with self._condition:            while self._readers > 0 or self._writers > 0:                self._condition.wait()            self._writers += 1    def release_write(self):        with self._condition:            self._writers -= 1            self._condition.notify_all()    # 上下文管理器支持    def read_lock(self):        return _ReadContext(self)    def write_lock(self):        return _WriteContext(self)class _ReadContext:    def __init__(self, rwlock):        self._rwlock = rwlock    def __enter__(self):        self._rwlock.acquire_read()    def __exit__(self, *args):        self._rwlock.release_read()class _WriteContext:    def __init__(self, rwlock):        self._rwlock = rwlock    def __enter__(self):        self._rwlock.acquire_write()    def __exit__(self, *args):        self._rwlock.release_write()

      6.4 无锁编程:使用 queue.Queue

      很多时候,用队列代替锁是更优雅的方案:

      import threadingimport queueimport time# 而不是用锁保护共享列表q = queue.Queue()  # 线程安全,内部已实现必要的锁def producer():    for i in range(10):        q.put(i)    q.put(None)    # 结束信号def consumer():    while True:        item = q.get()        if item is None:            break        process(item)

      queue.Queue 内部已使用 Condition 实现了线程安全的 put/get,用户无需手动加锁。


      7. 速查对照表

      原语threadingmultiprocessingasyncio核心用途
      互斥锁LockLockLock互斥访问临界区
      可重入锁RLockRLock同一线程可重入
      信号量SemaphoreSemaphoreSemaphore限制并发数量
      有界信号量BoundedSemaphoreBoundedSemaphoreBoundedSemaphore防 release 溢出
      条件变量ConditionConditionCondition生产者-消费者模式
      事件EventEventEvent一次性信号通知
      屏障BarrierBarrierBarrier(3.9+)多线程/协程同步点

      选择决策流程

      是 I/O 密集型 → 是否使用 asyncio? ├─ 是 → asyncio.Lock / Semaphore └─ 否 → threading.Lock / RLock是 CPU 密集型 → multiprocessing.Lock需要限制并发数 → Semaphore / BoundedSemaphore需要线程间通知 → Event(一次性)/ Condition(反复使用)需要阶段同步 → Barrier需要支持重入 → RLock需要读写分离 → 自定义 RWLock 或第三方库只需简单互斥 → Lock

      最新文章

      随机文章

      基本 文件 流程 错误 SQL 调试
      1. 请求信息 : 2026-08-21 20:56:28 HTTP/2.0 GET : https://f.mffb.com.cn/a/506900.html
      2. 运行时间 : 0.553303s [ 吞吐率:1.81req/s ] 内存消耗:4,836.47kb 文件加载:140
      3. 缓存信息 : 0 reads,0 writes
      4. 会话信息 : SESSION_ID=d39d13b092c6b071c01867e037fcd5a6
      1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
      2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
      3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
      4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
      5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
      6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
      7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
      8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
      9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
      10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
      11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
      12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
      13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
      14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
      15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
      16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
      17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
      18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
      19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
      20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
      21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
      22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
      23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
      24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
      25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
      26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
      27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
      28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
      29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
      30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
      31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
      32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
      33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
      34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
      35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
      36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
      37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
      38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
      39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
      40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
      41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
      42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
      43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
      44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
      45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
      46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
      47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
      48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
      49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
      50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
      51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
      52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
      53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
      54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
      55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
      56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
      57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
      58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
      59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
      60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
      61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
      62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
      63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
      64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
      65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
      66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
      67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
      68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
      69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
      70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
      71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
      72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
      73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
      74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
      75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
      76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
      77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
      78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
      79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
      80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
      81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
      82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
      83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
      84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
      85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
      86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
      87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
      88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
      89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
      90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
      91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
      92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
      93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
      94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
      95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
      96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
      97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
      98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
      99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
      100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
      101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
      102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
      103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
      104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
      105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
      106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
      107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
      108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
      109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
      110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
      111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
      112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
      113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
      114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
      115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
      116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
      117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
      118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
      119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
      120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
      121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
      122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
      123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
      124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
      125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
      126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
      127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
      128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
      129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
      130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
      131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
      132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
      133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
      134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
      135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
      136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
      137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
      138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
      139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
      140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
      1. CONNECT:[ UseTime:0.000896s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
      2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001537s ]
      3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.001111s ]
      4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.038561s ]
      5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001357s ]
      6. SELECT * FROM `set` [ RunTime:0.014570s ]
      7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001414s ]
      8. SELECT * FROM `article` WHERE `id` = 506900 LIMIT 1 [ RunTime:0.036155s ]
      9. UPDATE `article` SET `lasttime` = 1787316988 WHERE `id` = 506900 [ RunTime:0.069660s ]
      10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.010998s ]
      11. SELECT * FROM `article` WHERE `id` < 506900 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.023931s ]
      12. SELECT * FROM `article` WHERE `id` > 506900 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.038014s ]
      13. SELECT * FROM `article` WHERE `id` < 506900 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.026874s ]
      14. SELECT * FROM `article` WHERE `id` < 506900 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.023426s ]
      15. SELECT * FROM `article` WHERE `id` < 506900 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.076830s ]
      0.557030s