IT技术博客大学习 共学习 共进步

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

PHPor 的Blog 2010-11-24 21:12:47 浏览 2,922 次

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

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. Axure之变量的使用 (阅读 5,041)
  2. 深入PHP使用技巧之变量 (阅读 4,661)
  3. 从shell中向awk传递变量实例 (阅读 4,480)
  4. 变量在内存中的位置 (阅读 3,781)
  5. Linux的shell变量 (阅读 3,601)
  6. c语言全局变量和局部变量问题汇总 (阅读 3,583)
  7. PHP的可变变量名 (阅读 3,242)
  8. 详解Linux bash中的变量 (阅读 3,204)
  9. 如何获取一个变量的名字 (阅读 2,823)