Swoole Table 在协程中仅支持单次 set/get 和 TYPE_INT 的 incr/decr 操作;lock/unlock 非协程安全,读-改-写需用 Swoole\Lock 外部同步或移至 Task 进程;应显式调用 destroy() 清理内存。

Swoole Table 内存表本身不是为协程异步环境设计的,直接在协程中调用 set()/get() 看似能用,但存在并发安全风险和隐性崩溃可能——尤其当多个协程操作同一行、或混用锁与协程时。
关键点很明确:Table 的 lock/unlock 不是协程安全的,不能在协程中调用;而无锁的 set/get 对非 TYPE_INT 字段无法保证读-改-写原子性。
下面分场景说明怎么真正安全地读写:
Table 适合什么读写模式
- ✅ 单次
set($key, $value)或get($key)(纯覆盖/读取)是线程/进程安全的,底层有行级锁保障 - ✅
incr($key)/decr($key)仅对TYPE_INT字段有效,且是原子操作,协程中可放心使用 - ❌
lock($key)+ 修改 +unlock($key)绝对不要在协程里调用——会阻塞整个 Worker,破坏协程调度
非整型字段需要“读-改-写”怎么办
比如更新一个用户状态字符串、拼接日志、累加浮点统计值,这类操作必须加锁保护,但又不能用 Table 自带的 lock。解决方案是:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 用
Swoole\Lock(推荐FILE或MUTEX类型)做外部同步 - 锁粒度尽量小,只包裹真正需要互斥的代码段
- 示例:
$lock = new Swoole\Lock(SWOOLE_MUTEX); $lock->lock(); try { $data = $table->get('user_123'); $data['status'] = 'active'; $table->set('user_123', $data); } finally { $lock->unlock(); }⚠️ 注意:
Swoole\Lock是进程/线程安全的,但不是协程安全的——所以它只能用于同步上下文(如 onWorkerStart、onReceive),不能在 go() 协程里直接 new + lock。若必须在协程中做复杂操作,应把逻辑移到 Task 进程中处理。
更稳妥的协程友好替代方案
如果业务大量依赖“读-改-写”或混合类型数据,Table 就不是最优选。建议按场景切换:
- 计数类(在线人数、库存、PV)→ 改用
Swoole\Atomic(纯整数、协程安全、原子增减) - 结构化缓存(用户信息、配置)→ 改用
Swoole\Table+ 只做 set/get,不改写;变更走 Task 进程异步落库+刷新 - 高频共享状态(开关、版本号)→ 用
Swoole\Atomic或Swoole\SharedMemory手动管理
生命周期与内存清理必须显式控制
Table 基于 mmap,不随协程或 PHP 变量生命周期释放。务必在 onWorkerStop 或 onShutdown 中调用 $table->destroy(),否则重启后残留内存会导致 shmop_open(): unable to open or create shared memory segment。
不复杂但容易忽略。

















