php变量及参数传递

术语
zval容器,符号表,is_ref,refcount,cow,引用分离

<?php
# 值传递
$a =1;    // 一个zval容器
$b=$a;    // 两个zval容器,由于cow优化,仍然是一个zval容器
?>

<?php
# cow
$a = 1;
$b =$a;    // cow优化,一个容器
$b=2;    // 写操作,分离成两个zval容器了
?>

<?php
# 闭包use值传递
$var = 'Hello World';
$func=function ()use($var) {    // 闭包use,值传递(copy)
    var_dump($var);        // Hello World
    $var = "new value";    // 闭包内的值修改,不影响闭包外部的变量
};
$func();
var_dump($var);    // 不变,仍然是Hello World
?>

<?php
# 闭包use通过引用改变外部变量
$var = 'Hello World';
$func=function ()use(&$var) {    // 闭包use,试试传引用
    var_dump($var);    // Hello World
    $var = new stdClass();
};
$func();
var_dump($var);    // 引用发生了作用,输出object(stdClass)#2 (0) {}

?>

<?php
# 函数传递默认是值传递,对于对象则使用引用传递
$a = new stdClass();
function test($a) {
    $a->b=1;
    var_dump($a);
}
test($a);
var_dump($a);    // $a被改变了,输出:object(stdClass)#1 (1) {["b"]=>int(1) }
?>

<?php
# swoole下的参数传递
class Pool {
    private $_pool;
    public function __construct()
    {
        $this->_pool = new SplQueue();
        $this->_init();
    }
    private function _init(){
        for($i=0;$i<100;$i++) {
            $this->put($i);
        }
    }
    public function get() {
        return $this->_pool->dequeue();
    }
    public function put($item){
        $this->_pool->enqueue($item);
    }
    public function length(){
        return $this->_pool->count();
    }
}
$pool = new Pool();

class Server {
    private $_server;
    private $_pool;
    public function __construct(Pool $_pool)
    {
        $this->_pool = $_pool;
        $this->_server = new Swoole\Http\Server("0.0.0.0", 9500);
        $this->_server->set(
            [
                'worker_num' => 2,
//                'daemonize' => true,    // daemon
                'log_level' => SWOOLE_LOG_INFO,
            ]
        );
        $this->_server->on("request", [$this, "onRequest"]);

        $this->_server->start();
    }
    public function onRequest(\Swoole\Http\Request $request, \Swoole\Http\Response $response)
    {
        echo $this->_pool->get().PHP_EOL;
    }

}

$server = new Server($pool);

# 压测   ab -c 4 -n 4  http://127.0.0.1:9500/
# 输出:
#0
#1
#0
#1
# 分析:2个worker,4个并发,共4个请求,由于进程隔离,$pool对象发生了复制,而不是期望中输出0/1/2/3

?>

Refer:
http://php.net/manual/en/func...

相关推荐