Swoole自v6.0起支持SWOOLE_THREAD多线程Worker模式,基于pthread,共享内存需手动同步;启用需Server构造时传SWOOLE_THREAD标志、worker_num表示线程数、PHP启用ZTS,禁用pthreads扩展。

如何启用 SWOOLE_THREAD 模式?
只需在 Server 构造时传入 SWOOLE_THREAD 标志,并确保配置中未禁用线程支持:
$http = new Swoole\Http\Server('0.0.0.0', 9501, SWOOLE_THREAD);
$http->set([
'worker_num' => 4, // 线程数,不是进程数
]);
-
SWOOLE_THREAD是启动标志,必须显式传入,SWOOLE_BASE或SWOOLE_PROCESS(默认)都不行 -
worker_num此时代表「工作线程数」,不是进程数;线程间共享内存,但global、静态变量、static属性等**默认不安全**,需加锁或改用Swoole\Thread\Map - PHP 必须启用 ZTS(Zend Thread Safety)编译模式,可通过
php -i | grep "Thread Safety"确认输出为enabled;否则会直接报错:Fatal error: Swoole extension is not compiled with thread safety support - 扩展依赖:Swoole ≥ v6.0.0-alpha,且不能同时加载
pthreads扩展(冲突)
为什么不能直接 new Thread()?
你可能看到过类似 new Swoole\Thread(...) 的写法——那是 v6 之前废弃的实验性 API,已在 v6 正式版中移除。当前唯一受支持的线程模型,就是 SWOOLE_THREAD 模式下的 Server Worker 线程。
- 旧文档里出现的
Swoole\Thread类、Thread::getArguments()等,仅适用于 v5.x 及更早的非稳定分支,生产环境请勿使用 - 试图在
SWOOLE_PROCESS模式下手动调用线程类,会触发Segmentation fault或静默崩溃 - 如果你真需要 CLI 下的子线程(比如后台任务调度),应改用
swoole_process+useQueue做进程间通信,而非强行上线程
启用后哪些地方最容易出错?
线程模式下最典型的陷阱,不是性能问题,而是**内存可见性与竞态条件**——PHP 的弱类型 + 共享内存让 bug 难复现、难调试。
- 不要在回调中直接读写全局数组或静态属性,例如:
$GLOBALS['counter']++或MyClass::$count++—— 这是未定义行为,结果不可预测 - 避免用
file_get_contents、cURL等阻塞 I/O;虽在线程中不会卡住整个 Server,但仍浪费线程资源;应优先改用协程客户端(Swoole\Coroutine\Http\Client) -
onWorkerStart中初始化的资源(如数据库连接、Redis 实例)**不能跨线程复用**;每个线程需独立创建,或改用连接池 - 日志写入若共用同一文件句柄(如
fopen('app.log', 'a')),需加flock,否则内容会错乱或丢失










