Queue本质是协调信号通道,通过maxsize=1的阻塞get/put实现线程串行化:线程必须获取令牌才能更新共享计数器,sleep仅用于可视化节奏,同步保障源于Queue原子操作而非延时。

在初级并发练习中,用 Queue 结合线程的 sleep 实现“同步计数”,本质不是靠 Queue 做同步(它本身线程安全),而是利用它作为**协调信号通道**,配合 time.sleep 控制节奏,让多个线程按顺序、可预期地更新共享计数器。关键在于:避免竞态,同时体现“等待-唤醒”逻辑,又不直接用 Lock 或 Event ——适合初学者理解协作式控制。
用 Queue 当“通行证”控制执行顺序
queue.Queue 的 get() 和 put() 是阻塞操作,天然适合做线程间简单协调。比如初始化队列放一个初始令牌(如 1),每个线程必须先 get() 到令牌才能执行计数 + sleep + 输出,再 put() 回去,让下一个线程拿到。这样就形成串行化效果:
- 队列大小设为 1,保证任意时刻最多一个线程能“持证上岗”
- 每个线程拿到令牌后才读/写共享变量(如
counter),更新完立刻归还 -
sleep放在计数后、归还前,模拟“工作耗时”,让观察者看清顺序
代码结构要点(Python 示例)
假设启动 3 个线程,目标是让它们按序打印 “Thread-X: count=1”, “Thread-Y: count=2”, … 直到 count=6:
- 定义全局
counter = 0(注意:仅用于演示;真实场景应避免裸全局变量) - 创建
q = queue.Queue(maxsize=1),先q.put(1)发放首张通行证 - 每个线程函数:循环中
q.get()→counter += 1→print(...)→time.sleep(0.1)→q.put(1) - 用
threading.Thread启动,全部start()后调用join()
为什么 sleep 不破坏同步?
sleep 在 get() 之后、put() 之前执行,此时该线程已独占令牌,其他线程还在 get() 处阻塞等待。所以 sleep 只是延长了当前线程持有令牌的时间,并不影响临界区(counter 更新)的互斥性——真正保障同步的是 Queue 的原子性阻塞操作,sleep 只是让过程“看得见”。
注意事项和常见误区
这种做法是教学向的简化模型,实际需注意:
- 不要依赖
sleep实现同步逻辑(它不能保证时序,只辅助观察) - 若去掉
sleep,输出依然有序,证明同步由Queue保证,而非延时 - 若想让所有线程“并发推进但不冲突”,应改用
queue.Queue传递任务(如每个线程从队列取一个待计数值),而非用它做锁 - 初学易误写成多个线程同时
put()导致队列满异常,务必确保maxsize=1且每次get后必有对应put

















