我们在首次使用 Swoole 框架时候发现有三类变量问题需要主要,问题的主要造成因素应该是 Swoole 常驻内容变量内存共享导致的主要有一下三类
- 使用 global 关键词声明的变量
- 使用 static 关键词声明的类静态变量、函数静态变量
- PHP的超全局变量,包括$_GET,$_POST,$GLOBALS等
这三种类型的变量在 Swoole 模式下都存在并发安全问题
Swoole 变量问题
A,B,C三人依次访问设置变量分别为1,2,3程序返回时分别对A,B,C三人的请求进行延迟3,2,1秒按照正常逻辑来看A,B,C三人访问设置的1,2,3那么对应返回的值就是设置的值,但是通过使用swoole发现三人返回的结果为最后一个人设置的值也就是3这种情况就是我们刚才所说的三类变量问题
Swoole 全局变量 Global 问题演示
// 数据混乱演示
public function index()
{
// 并发安全问题,会出现数据混乱
// 第一次访问 http://192.168.100.103:8088/Context/index?i=1
// 第二次访问 http://192.168.100.103:8088/Context/index?i=2
// 返回返回查看第一次访问返回的结果不是预期的1,而是2,所以说这种全局变量保存上下文资源存在并发安全问题
global $aaa;
$aaa = $this->request->param('i');
if ($this->request->param('i') == 1) {
Coroutine::sleep(3);
}
$this->test1();
return $aaa;
}
protected function test1()
{
global $aaa;
dump($aaa);
}
Swoole 静态变量 Static 问题演示
class StaticAaa extends BaseController
{
protected static $i;
// 数据混乱演示
public function index()
{
// 并发安全问题,会出现数据混乱
// 第一次访问 http://192.168.100.103:8088/StaticAaa/index?i=1
// 第二次访问 http://192.168.100.103:8088/StaticAaa/index?i=2
// 返回返回查看第一次访问返回的结果不是预期的1,而是2,所以说这种全局变量保存上下文资源存在并发安全问题
self::$i = $this->request->param('i');
if ($this->request->param('i') == 1) {
Coroutine::sleep(2);
}
return self::$i;
}
}
Swoole 超级全局变量 $_GET 问题演示
// 数据混乱演示
public function index()
{
// 并发安全问题,会出现数据混乱
// 第一次访问 http://192.168.100.103:8088/StaticAaa/index?i=1
// 第二次访问 http://192.168.100.103:8088/StaticAaa/index?i=2
// 返回返回查看第一次访问返回的结果不是预期的1,而是2,所以说这种全局变量保存上下文资源存在并发安全问题
$_GET['i'] = $this->request->param('i');
if ($this->request->param('i') == 1) {
Coroutine::sleep(2);
}
return $_GET['i'];
}
Swoole 三类变量问题解决方案
通过阅读文档发现 swoole 已经给出了解决的方法,我们只需要使用swoole 上下文 Context 类保存上下文临时数据即可。
文档地址
// 正确实例
public function index()
{
// 第一次访问 http://192.168.100.103:8088/Ok/index?i=1
// 第二次访问 http://192.168.100.103:8088/Ok/index?i=2
$contextKey = 'aaa';
$i = $this->request->param('i');
\think\swoole\coroutine\Context::setData($contextKey, $i);
if ($this->request->param('i') == 1) {
Coroutine::sleep(2);
}
return \think\swoole\coroutine\Context::getData($contextKey);
}
关于php使用 swoole 框架静态变量,全局变量并发安全问题已经解决了
评论已关闭