IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

PHP 中对变量unset,可以销毁变量中的资源

PHPor 的Blog 2010-11-24 21:12:47 累计浏览 3,037 次
本机暂存

提示: 您可以先看结论,结论在文章最后。

start...

我们先看两段代码:

以下是代码片段:
<?php        
            
    while($i++ < 1000) {        
            $a = fsockopen("10.55.38.18",11211);        
            unset($a);        
            sleep(3);        
    }        
            
    ?>    
以下是代码片段:
    <?php        
            
    while($i++ < 1000) {        
            $a = fsockopen("10.55.38.18",11211);        
            sleep(3);        
    }        
            
    ?>    

分析:
        
  1. 两段测试代码只有一个unset的区别,我们只是在测试unset是否是必要的    
  2. 因为我们打开的连接根本就没有关闭,在变量被unset或被重新赋值时,该变量所使用的连接是否会自动关闭呢?如果不能自动关闭,代码一直运行将会产生大量的连接,这是我们最担心的。    
  3. 其实我们完全可以不必做这种测试,我们可以在销毁变量前显示关闭连接的,我们也最好这么做,虽然多了几行代码,但是代码的可读性就提高了很多
测试
1.
strace  -tt php a.php
        
  1.     
    10:57:43.474622 socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
            
  2.     
    10:57:43.474705 fcntl(3, F_GETFL)       = 0x2 (flags O_RDWR)
            
  3.     
    10:57:43.474787 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
            
  4.     
    10:57:43.474898 connect(3, {sa_family=AF_INET, sin_port=htons(11211), sin_addr=inet_addr("10.55.38.18")}, 16) = -1 EINPROGRESS (Operation now in progress)
            
  5.     
    10:57:43.474984 poll([{fd=3, events=POLLIN|POLLOUT|POLLERR|POLLHUP, revents=POLLOUT}], 1, 60000) = 1
            
  6.     
    10:57:43.523892 getsockopt(3, SOL_SOCKET, SO_ERROR, [29042414236729344], [4]) = 0
            
  7.     
    10:57:43.523974 fcntl(3, F_SETFL, O_RDWR) = 0
            
  8.     
    10:57:43.524046 close(3)                = 0
            
  9.     
    10:57:43.524124 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
            
  10.     
    10:57:43.524201 rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0
            
  11.     
    10:57:43.524269 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
            
  12.     
    10:57:43.524331 nanosleep({3, 0}, {3, 0}) = 0
        

2.
strace  -tt php b.php
        
  1.     
    11:13:24.554959 socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
            
  2.     
    11:13:24.554998 fcntl(3, F_GETFL)       = 0x2 (flags O_RDWR)
            
  3.     
    11:13:24.555029 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
            
  4.     
    11:13:24.555063 connect(3, {sa_family=AF_INET, sin_port=htons(11211), sin_addr=inet_addr("10.55.38.18")}, 16) = -1 EINPROGRESS (Operation now in progress)
            
  5.     
    11:13:24.555131 poll([{fd=3, events=POLLIN|POLLOUT|POLLERR|POLLHUP, revents=POLLOUT}], 1, 60000) = 1
            
  6.     
    11:13:24.615839 getsockopt(3, SOL_SOCKET, SO_ERROR, [339302416384], [4]) = 0
            
  7.     
    11:13:24.615924 fcntl(3, F_SETFL, O_RDWR) = 0
            
  8.     
    11:13:24.616017 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
            
  9.     
    11:13:24.616098 rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0
            
  10.     
    11:13:24.616173 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
            
  11.     
    11:13:24.616250 nanosleep({3, 0}, {3, 0}) = 0
            
  12.     
    ...
            
  13.     
    ...
            
  14.     
    11:13:27.618228 socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 4
            
  15.     
    11:13:27.618302 fcntl(4, F_GETFL)       = 0x2 (flags O_RDWR)
            
  16.     
    11:13:27.618368 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0
            
  17.     
    11:13:27.618453 connect(4, {sa_family=AF_INET, sin_port=htons(11211), sin_addr=inet_addr("10.55.38.18")}, 16) = -1 EINPROGRESS (Operation now in progress)
            
  18.     
    11:13:27.618598 poll([{fd=4, events=POLLIN|POLLOUT|POLLERR|POLLHUP, revents=POLLOUT}], 1, 60000) = 1
            
  19.     
    11:13:27.676299 getsockopt(4, SOL_SOCKET, SO_ERROR, [339302416384], [4]) = 0
            
  20.     
    11:13:27.676381 fcntl(4, F_SETFL, O_RDWR) = 0
            
  21.     
    11:13:27.676679 close(3)                = 0
            
  22.     
    11:13:27.676776 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
            
  23.     
    11:13:27.676858 rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0
            
  24.     
    11:13:27.676934 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
            
  25.     
    11:13:27.677013 nanosleep({3, 0},  <unfinished ...>
        
分析:
        
  1. 测试1中,我们观察 4~8行,打开的连接时立即被关闭的,因为遇到了unset函数,说明: 在变量被unset时,变量所标示的连接立即关闭    
  2. 测试2中,我们观察14~21行,发现打开的连接是4,但是关闭的连接是3,但是3是上次sleep之前的一个连接,说明: 在变量被重新赋值时,变量所标示的连接立即关闭
结论:
        
  1. 在变量被重新赋值时,变量所标示的连接立即关闭    
  2. 在变量被unset时,变量所标示的连接立即关闭    
  3. 不要写这么含蓄的代码。
        
              
    • 如果你是一个连接变量,重新赋值前最好close一下;        
    • 如果你是一个对象,在析构函数中关闭你的连接;当然如果你使用的是长连接,就不必这么做了    

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. 使用gettext来支持PHP的多语言 (累计阅读 39,267)
  2. WordPress插件开发 -- 在插件使用数据库存储数据 (累计阅读 29,163)
  3. Paypal接口详细代码(PHP版,非API接口) (累计阅读 19,407)
  4. 我的PHP,Python和Ruby之路 (累计阅读 13,146)
  5. include(“./file.php”)和include(“file.php”)区别 (累计阅读 12,788)
  6. 15个最好的免费开源电子商务平台 (累计阅读 12,540)
  7. Redis消息队列的若干实现方式 (累计阅读 12,087)
  8. 到底什么是MVC? (累计阅读 11,865)
  9. 整理了一份招PHP高级工程师的面试题 (累计阅读 11,708)
  10. Rolling cURL: PHP并发最佳实践 (累计阅读 11,486)