SwooleAtomic是映射到共享内存的无锁整数计数器,绕过PHP引用计数与ZVAL机制,仅支持int64,需在主进程或onWorkerStart中初始化以实现多进程实时可见。
SwooleAtomic 对象底层映射到共享内存,并通过 CPU 原子指令(如 __sync_fetch_and_add)直接操作内存地址,完全绕过 PHP 的 ZVAL 和引用计数机制。这意味着:
– 它不能被 unset() 或赋值给另一个变量后“复制”;
– 多个 Worker 进程中对同一个 SwooleAtomic 实例的读写,看到的是同一块物理内存;
– 你不能用 var_dump($atomic) 查看其“值”,必须调用 get() 才能获取当前整数值。
PHP 变量默认是进程私有的:每个 Worker 进程 fork 后拥有独立的内存空间,修改 $counter = 0 对其他进程毫无影响。而 SwooleAtomic 是显式共享的:
– 必须在主进程或 onWorkerStart 中初始化一次,之后所有 Worker 都可复用该对象;
– 调用 incr() 后,任意 Worker 立即调用 get() 都能拿到最新值;
– 没有“同步延迟”,也不需要 pcntl_fork 后重新创建 —— 共享内存地址在 fork 前就已固定。
SwooleAtomic 的设计目标非常明确:高性能无锁整数计数。它不支持:
– 字符串、浮点数、数组等任何非整型字段;
– $atomic->set("123") 会静默截断为 123,但 $atomic->set(3.14) 会被转成 3;
– 不存在 ++$atomic 这类语法糖,必须显式调用 add()、sub()、cmpset();
– 错误地传入超范围整数(如大于 PHP_INT_MAX 的 uint64 值)可能导致溢出,返回负值,需自行校验边界。
PHP 变量生命周期由 Zend GC 管理,而 SwooleAtomic 的内存由 Swoole 内存管理器分配,销毁时机取决于:
– 主进程退出时自动释放对应共享内存段;
– 若在 Task 进程中 new 一个 SwooleAtomic,它不会被 Worker 进程看到,且 Task 结束后该实例立即失效(但底层共享内存未回收,除非主进程也退出);
– 不要试图在 onWorkerStop 中手动释放它 —— 没有 destroy() 方法,调用 unset() 只是断开 PHP 对象引用,不影响底层原子变量状态。
立即学习“PHP免费学习笔记(深入)”;
实际用的时候最容易忽略的是:Atomic 的“全局性”完全依赖初始化位置和作用域。在onReceive 回调里每次 new 一个 SwooleAtomic,得到的只是独立的、无法跨进程通信的普通对象 —— 它根本没进共享内存。