首页
下载
文档
问答社区
视频
捐赠
源代码
AI 助理
赞助商
CRMEB
Apipost
腾讯云
微擎
禅道
51Talk
商业产品
Swoole AI 智能文档翻译器
Swoole-Compiler PHP 代码加密器
CRMEB 新零售社交电商系统
登录
注册
全部
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
发表新帖
在swoole的协程中禁止使用全局变量,那是不是可以是类的静态变量来在协程之间传递数据
我们想实现一个功能:从缓存中获取数据,如果多个协程同时获取,只有一个协程能获取到,其他的协程等到数据获取完成之后返回,想通过类的静态变量来在协程之间共享数据,是否可行?我们的实现如下:是否存在问题? <?php use Swoole\Coroutine\Redis; use Swoole\Coroutine\Channel; use Swoole\Coroutine\Scheduler; use Swoole\Coroutine; use Swoole\Timer; /** 多个并发的时候只有一个是实际去操作的 */ class once{ public static $tags = []; public static function Req($tag){ $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."]Req!".$cid,PHP_EOL; if(isset(static::$tags[$tag])){ return false; } static::$tags[$tag] = []; return true; } public static function Wait($tag){ $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."]Wait!".$cid,PHP_EOL; $cid = Coroutine::getCid(); static::$tags[$tag][] = $cid; Coroutine::yield(); } public static function Release($tag){ $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."]Release!".$cid,PHP_EOL; if(isset(static::$tags[$tag]) && static::$tags[$tag]){ foreach (static::$tags[$tag] as $cid) { Coroutine::resume($cid); } } unset(static::$tags[$tag]); } } class userCache{ private static $_ins; public static function getIns(){ if(empty(static::$_ins)){ static::$_ins = new static(); } return static::$_ins; } public $cache = []; public function GetUser($userId){ return isset($this->cache[$userId])?$this->cache[$userId]:null; } public function setUser($userInfo){ $userId = $userInfo['userId']; $this->cache[$userId] = $userInfo; } } $keyUser = "user_"; function getUserInfo($userId){ global $keyUser; $userCache = userCache::getIns(); $user = $userCache->getUser($userId); if(empty($user)){ $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."] 没有获取到用户信息".PHP_EOL; $tag = $keyUser.$userId; if(!once::Req($tag)){ echo "[".date('Y-m-d H:i:s')."]没有获取到锁!".$cid,PHP_EOL; once::Wait($tag); echo "[".date('Y-m-d H:i:s')."]获取数据!".$cid,PHP_EOL; $user = $userCache->getUser($userId); }else{ echo "[".date('Y-m-d H:i:s')."]获取到锁!".$cid,PHP_EOL; Coroutine::defer(function() use ($tag){ once::Release($tag); }); echo "[".date('Y-m-d H:i:s')."]获取数据!".$cid,PHP_EOL; $int = 2; Coroutine::sleep($int); $user = [ 'userId'=>$userId, 'name'=>'name_'.$userId, ]; $userCache->setUser($user); } echo "[".date('Y-m-d H:i:s')."]获取到数据!".$cid,PHP_EOL; //var_dump($user); } return $user; } function doSomeThing(){ $userId = 12345; $user = getUserInfo($userId); $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."]返回数据!".$cid,PHP_EOL; var_dump($user); } function main(){ for($i=0;$i<5;$i++){ go(function(){ /*这个就是一个正常的的server流程的*/ doSomeThing(); }); } } $s = time(); $scheduler = new Swoole\Coroutine\Scheduler; $scheduler->add('main'); $scheduler->start(); echo __FILE__.'.'.__LINE__,PHP_EOL; $diff = time() - $s; echo "DIFF:".$diff,PHP_EOL;
发布于4年前 · 26 次浏览 · 来自
提问
w
will9900
我们想实现一个功能:从缓存中获取数据,如果多个协程同时获取,只有一个协程能获取到,其他的协程等到数据获取完成之后返回,想通过类的静态变量来在协程之间共享数据,是否可行?我们的实现如下:是否存在问题? <?php use Swoole\Coroutine\Redis; use Swoole\Coroutine\Channel; use Swoole\Coroutine\Scheduler; use Swoole\Coroutine; use Swoole\Timer; /** 多个并发的时候只有一个是实际去操作的 */ class once{ public static $tags = []; public static function Req($tag){ $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."]Req!".$cid,PHP_EOL; if(isset(static::$tags[$tag])){ return false; } static::$tags[$tag] = []; return true; } public static function Wait($tag){ $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."]Wait!".$cid,PHP_EOL; $cid = Coroutine::getCid(); static::$tags[$tag][] = $cid; Coroutine::yield(); } public static function Release($tag){ $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."]Release!".$cid,PHP_EOL; if(isset(static::$tags[$tag]) && static::$tags[$tag]){ foreach (static::$tags[$tag] as $cid) { Coroutine::resume($cid); } } unset(static::$tags[$tag]); } } class userCache{ private static $_ins; public static function getIns(){ if(empty(static::$_ins)){ static::$_ins = new static(); } return static::$_ins; } public $cache = []; public function GetUser($userId){ return isset($this->cache[$userId])?$this->cache[$userId]:null; } public function setUser($userInfo){ $userId = $userInfo['userId']; $this->cache[$userId] = $userInfo; } } $keyUser = "user_"; function getUserInfo($userId){ global $keyUser; $userCache = userCache::getIns(); $user = $userCache->getUser($userId); if(empty($user)){ $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."] 没有获取到用户信息".PHP_EOL; $tag = $keyUser.$userId; if(!once::Req($tag)){ echo "[".date('Y-m-d H:i:s')."]没有获取到锁!".$cid,PHP_EOL; once::Wait($tag); echo "[".date('Y-m-d H:i:s')."]获取数据!".$cid,PHP_EOL; $user = $userCache->getUser($userId); }else{ echo "[".date('Y-m-d H:i:s')."]获取到锁!".$cid,PHP_EOL; Coroutine::defer(function() use ($tag){ once::Release($tag); }); echo "[".date('Y-m-d H:i:s')."]获取数据!".$cid,PHP_EOL; $int = 2; Coroutine::sleep($int); $user = [ 'userId'=>$userId, 'name'=>'name_'.$userId, ]; $userCache->setUser($user); } echo "[".date('Y-m-d H:i:s')."]获取到数据!".$cid,PHP_EOL; //var_dump($user); } return $user; } function doSomeThing(){ $userId = 12345; $user = getUserInfo($userId); $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."]返回数据!".$cid,PHP_EOL; var_dump($user); } function main(){ for($i=0;$i<5;$i++){ go(function(){ /*这个就是一个正常的的server流程的*/ doSomeThing(); }); } } $s = time(); $scheduler = new Swoole\Coroutine\Scheduler; $scheduler->add('main'); $scheduler->start(); echo __FILE__.'.'.__LINE__,PHP_EOL; $diff = time() - $s; echo "DIFF:".$diff,PHP_EOL;
赞
0
分享
收藏
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
评论
2020-03-12
Twosee
如果是标准的CSP并发模型, 任何数据的传递都需要通过Channel 像Coroutine::yield这样的API不建议使用的, Channel->pop具有相同的效果并且能够传递数据 至于全局变量, 不是不能用, 而是不可以像FPM下那么用, 只要通过cid来进行正确的分割就没有关系
赞
0
回复
2020-03-12
w
will9900
我现在修改了一下,是channel->pop来实现了 <?php use Swoole\Coroutine\Redis; use Swoole\Coroutine\Channel; use Swoole\Coroutine\Scheduler; use Swoole\Coroutine; use Swoole\Timer; /** 多个并发的时候只有一个是实际去操作的 */ class once{ public static $tagsCh = []; public static $tags = []; public static function Req($tag){ $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."]Req!".$cid,PHP_EOL; if(isset(static::$tagsCh[$tag])){ return false; } static::$tags[$tag] = 0; static::$tagsCh[$tag] = new Channel(1); return true; } public static function Wait($tag){ $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."]Wait!".$cid,PHP_EOL; static::$tags[$tag] += 1; static::$tagsCh[$tag]->pop(); } public static function Release($tag){ $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."]Release!".$cid,PHP_EOL; if(isset(static::$tags[$tag])){ for($i=0;$i<static::$tags[$tag];$i++){ static::$tagsCh[$tag]->push(true); } unset(static::$tags[$tag]); } if(isset(static::$tagsCh[$tag])){ static::$tagsCh[$tag]->close(); unset(static::$tagsCh[$tag]); } } } class userCache{ private static $_ins; public static function getIns(){ if(empty(static::$_ins)){ static::$_ins = new static(); } return static::$_ins; } public $cache = []; public function GetUser($userId){ return isset($this->cache[$userId])?$this->cache[$userId]:null; } public function setUser($userInfo){ $userId = $userInfo['userId']; $this->cache[$userId] = $userInfo; } } $keyUser = "user_"; function getUserInfo($userId){ global $keyUser; $userCache = userCache::getIns(); $user = $userCache->getUser($userId); if(empty($user)){ $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."] 没有获取到用户信息".PHP_EOL; $tag = $keyUser.$userId; if(!once::Req($tag)){ echo "[".date('Y-m-d H:i:s')."]没有获取到锁!".$cid,PHP_EOL; once::Wait($tag); echo "[".date('Y-m-d H:i:s')."]获取数据!".$cid,PHP_EOL; $user = $userCache->getUser($userId); }else{ echo "[".date('Y-m-d H:i:s')."]获取到锁!".$cid,PHP_EOL; Coroutine::defer(function() use ($tag){ once::Release($tag); }); echo "[".date('Y-m-d H:i:s')."]获取数据!".$cid,PHP_EOL; $int = 2; Coroutine::sleep($int); $user = [ 'userId'=>$userId, 'name'=>'name_'.$userId, ]; $userCache->setUser($user); } echo "[".date('Y-m-d H:i:s')."]获取到数据!".$cid,PHP_EOL; } return $user; } function doSomeThing(){ $userId = 12345; $user = getUserInfo($userId); $cid = Coroutine::getCid(); echo "[".date('Y-m-d H:i:s')."]返回数据!".$cid,PHP_EOL; var_dump($user); } function main(){ for($i=0;$i<5;$i++){ go(function(){ /*这个就是一个正常的的server流程的*/ doSomeThing(); }); } } $s = time(); $scheduler = new Swoole\Coroutine\Scheduler; $scheduler->add('main'); $scheduler->start(); // Co\run('main'); echo __FILE__.'.'.__LINE__,PHP_EOL; $diff = time() - $s; echo "DIFF:".$diff,PHP_EOL;
赞
0
回复
微信公众号
热门内容
暂无回复的问答
- CodeGalaxy K3s 轻量集群节点之间如何实现负载均衡
- 关于openssl CURL WARNING swSSL_connect: SSL_connect(fd=69) failed. Error: error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small[1|394]
- 多个模型如何进行事务异常回退?
- websocket开启wss报错
- 协程tcp服务器如何使用多进程?recv()方法接收信息,打印出来的pid一直是同一个。没用使用到多进程啊。