php文件的锁定机制

如果要并发读取、写入一个文件,就要对文件加锁,防止读、写混乱,造成结果有误,php使用函数 bool flock(int handle, int operation, int &wouldlock)函数对文件加锁

,详细如下面的例子:

<html>
<head>
    <title>
        留言板
    </title>
</head>
<body>
<?php
    /**
     * 如果需要并发读取某文件,问了防止读写混乱,就要对打开的文件加锁
     * bool flock(int handle, int operation, int &wouldblock)函数可以对文件加锁
     * handle是一个文件指针,operation指定锁的类型,锁的类型包括:
     * LOCK_SH 共享锁,读取文件时使用
     * LOCK_EX 独占锁,写入文件时使用
     * LOCK_UN 释放锁,上面两种锁都用它来释放(ps:当文件被fclose()掉后,锁也会被释放)
     * LOCK_NB 附加锁,不过不希望flock()在锁定时堵塞,就应该在上面锁定后,再加上该锁
     * 锁定阻塞是指已经被flock()锁定的文件,再次被flock()时,flock()函数就会挂起,解决方法除了
     * 上面加上附加锁,还可以指定第三个参数wouldblock为1,意思是当文件锁定时会阻挡其他进程。
     */
            
    echo "<h1>网络留言板</h1>";
    $fileName = "guestbook.txt";
    //调用自定义函数,读取留言板中的消息
    if(file_exists($fileName))
        readMessage($fileName);
                
    //如果用户提交了留言,就调用自定义函数,写入到留言板中
    if(isset($_POST['submitBtn']))
        writeMessage($fileName, $_POST['username'] . $_POST['title'] . $_POST['content']);
                    
    function readMessage($fileName)
    {
        $fileHandle = fopen($fileName, "r");
        flock($fileHandle, LOCK_SH);
        $allMessages = "";
        //循环读取文件中的留言
        while(!feof($fileHandle))
            $allMessages .= fgets($fileHandle);
        $messageArray = explode("|", $allMessages);
                    
        foreach ($messageArray as $message)
        {
            echo $message . "<br />";
        }
        flock($fileHandle, LOCK_UN);
        fclose($fileHandle);
                    
    }
    //写入留言板
    function writeMessage($fileName, $message)
    {
        $fileHandle = fopen($fileName, "a");
        flock($fileHandle, LOCK_EX);
        $message .= "|";
        fwrite($fileHandle, $message) or die("留言写入失败");
        flock($fileHandle, LOCK_UN);
        fclose($fileHandle);    
    }
    /**
     * 如果要防止锁定阻塞,可以附加LOCK_NB锁
     * flock($fileHandle, LOCK_EX+LOCK_NB);
     * flock($fileHandle, LOCK_UN+LOCK_NB);
     */
?>
    <form action="file5.php" method="post">
        昵称:<input type="text" name="username" value="请输入昵称" onfocus="if(this.value=='请输入昵称') this.value=''" onblur="if(this.value=='') this.value='请输入昵称'"> <br />
        标题:<input type="text" name="title" value="请输入标题" onfocus="if(this.value=='请输入标题') this.value=''" onblur="if(this.value=='') this.value='请输入标题'"><br />
        留言:<textarea name="content" rows=4 cols=40 onfocus="if(this.value=='请输入留言') this.value=''" onblur="if(this.value=='') this.value='请输入留言'">请输入留言</textarea><br />
        <input type="submit" name="submitBtn" value="提交">
    </form>
    </body>
</html>

发表评论

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

(Spamcheck Enabled)