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

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

start…

我们先看两段代码:

测试代码 a.php
        

  1.     
    <?php

        

  2.     

  3.     

        

  4.     

  5.     
    while($i++ < 1000) {

        

  6.     

  7.     
            $a = fsockopen("10.55.38.18",11211);

        

  8.     

  9.     
            unset($a);

        

  10.     

  11.     
            sleep(3);

        

  12.     

  13.     
    }

        

  14.     

  15.     

        

  16.     

  17.     
    ?>

        

测试代码 b.php
        

  1.     
    <?php

        

  2.     

  3.     

        

  4.     

  5.     
    while($i++ < 1000) {

        

  6.     

  7.     
            $a = fsockopen("10.55.38.18",11211);

        

  8.     

  9.     
            sleep(3);

        

  10.     

  11.     
    }

        

  12.     

  13.     

        

  14.     

  15.     
    ?>

        

分析:

        

  1. 两段测试代码只有一个unset的区别,我们只是在测试unset是否是必要的
  2.     

  3. 因为我们打开的连接根本就没有关闭,在变量被unset或被重新赋值时,该变量所使用的连接是否会自动关闭呢?如果不能自动关闭,代码一直运行将会产生大量的连接,这是我们最担心的。
  4.     

  5. 其实我们完全可以不必做这种测试,我们可以在销毁变量前显示关闭连接的,我们也最好这么做,虽然多了几行代码,但是代码的可读性就提高了很多

测试

1.

strace  -tt php a.php
        

  1.     
    10:57:43.474622 socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3

        

  2.     

  3.     
    10:57:43.474705 fcntl(3, F_GETFL)       = 0x2 (flags O_RDWR)

        

  4.     

  5.     
    10:57:43.474787 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0

        

  6.     

  7.     
    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)

        

  8.     

  9.     
    10:57:43.474984 poll([{fd=3, events=POLLIN|POLLOUT|POLLERR|POLLHUP, revents=POLLOUT}], 1, 60000) = 1

        

  10.     

  11.     
    10:57:43.523892 getsockopt(3, SOL_SOCKET, SO_ERROR, [29042414236729344], [4]) = 0

        

  12.     

  13.     
    10:57:43.523974 fcntl(3, F_SETFL, O_RDWR) = 0

        

  14.     

  15.     
    10:57:43.524046 close(3)                = 0

        

  16.     

  17.     
    10:57:43.524124 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0

        

  18.     

  19.     
    10:57:43.524201 rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0

        

  20.     

  21.     
    10:57:43.524269 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0

        

  22.     

  23.     
    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.     

  3.     
    11:13:24.554998 fcntl(3, F_GETFL)       = 0x2 (flags O_RDWR)

        

  4.     

  5.     
    11:13:24.555029 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0

        

  6.     

  7.     
    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)

        

  8.     

  9.     
    11:13:24.555131 poll([{fd=3, events=POLLIN|POLLOUT|POLLERR|POLLHUP, revents=POLLOUT}], 1, 60000) = 1

        

  10.     

  11.     
    11:13:24.615839 getsockopt(3, SOL_SOCKET, SO_ERROR, [339302416384], [4]) = 0

        

  12.     

  13.     
    11:13:24.615924 fcntl(3, F_SETFL, O_RDWR) = 0

        

  14.     

  15.     
    11:13:24.616017 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0

        

  16.     

  17.     
    11:13:24.616098 rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0

        

  18.     

  19.     
    11:13:24.616173 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0

        

  20.     

  21.     
    11:13:24.616250 nanosleep({3, 0}, {3, 0}) = 0

        

  22.     

  23.     

        

  24.     

  25.     

        

  26.     

  27.     
    11:13:27.618228 socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 4

        

  28.     

  29.     
    11:13:27.618302 fcntl(4, F_GETFL)       = 0x2 (flags O_RDWR)

        

  30.     

  31.     
    11:13:27.618368 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0

        

  32.     

  33.     
    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)

        

  34.     

  35.     
    11:13:27.618598 poll([{fd=4, events=POLLIN|POLLOUT|POLLERR|POLLHUP, revents=POLLOUT}], 1, 60000) = 1

        

  36.     

  37.     
    11:13:27.676299 getsockopt(4, SOL_SOCKET, SO_ERROR, [339302416384], [4]) = 0

        

  38.     

  39.     
    11:13:27.676381 fcntl(4, F_SETFL, O_RDWR) = 0

        

  40.     

  41.     
    11:13:27.676679 close(3)                = 0

        

  42.     

  43.     
    11:13:27.676776 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0

        

  44.     

  45.     
    11:13:27.676858 rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0

        

  46.     

  47.     
    11:13:27.676934 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0

        

  48.     

  49.     
    11:13:27.677013 nanosleep({3, 0},  <unfinished …>

        

分析:

        

  1. 测试1中,我们观察 4~8行,打开的连接时立即被关闭的,因为遇到了unset函数,说明: 在变量被unset时,变量所标示的连接立即关闭
  2.     

  3. 测试2中,我们观察14~21行,发现打开的连接是4,但是关闭的连接是3,但是3是上次sleep之前的一个连接,说明: 在变量被重新赋值时,变量所标示的连接立即关闭

结论:

        

  1. 在变量被重新赋值时,变量所标示的连接立即关闭
  2.     

  3. 在变量被unset时,变量所标示的连接立即关闭
  4.     

  5. 不要写这么含蓄的代码。
        
              

    • 如果你是一个连接变量,重新赋值前最好close一下;
    •         

    • 如果你是一个对象,在析构函数中关闭你的连接;当然如果你使用的是长连接,就不必这么做了
    •     

        

留下评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据