php多线程操作同一文件-待续

编程爱好者联盟 2016-11-22

同意文件操作同意文件的问题在于逻辑有些地方不合适,如果多个线程同时写入,在不加锁的情况下,可能导致得到结果不如意,为了安全,和脏读(数据库的词),应该使用排他锁,这就意味着每次只能被一个线程操作。其他线程只能等待,如果超时则会报错。

关键函数:
 fopen()  // 打开文件或一个http地址,形成一个文件流
 flock()  // 对文件加锁及解锁
 fwrite()  // 对文件读写操作
 fclose()  // 关闭文件流
fopen()   resource fopen ( string $filename , string $mode [, bool $use_include_path = false [, resource $context ]] )
 
 文件打开模式:
 'r' 只读方式打开,将文件指针指向文件头。  
 'r+' 读写方式打开,将文件指针指向文件头。  
 'w' 写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。  
 'w+' 读写方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。  
 'a' 写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。  
 'a+' 读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。  
 'x' 创建并以写入方式打开,将文件指针指向文件头。如果文件已存在,则 fopen() 调用失败并返回 FALSE,并生成一条 E_WARNING 级别的错误信息。如果文件不存在则尝试创建之。这和给 底层的 open(2) 系统调用指定 O_EXCL|O_CREAT 标记是等价的。  
 'x+' 创建并以读写方式打开,其他的行为和 'x' 一样。
flock()   bool flock ( resource $handle , int $operation [, int &$wouldblock ] )
 
 
 handle
 文件系统指针,是典型地由 fopen() 创建的 resource(资源)。
 operation
 operation 可以是以下值之一: 
 ◦ LOCK_SH取得共享锁定(读取的程序)。  
 ◦ LOCK_EX 取得独占锁定(写入的程序。  
 ◦ LOCK_UN 释放锁定(无论共享或独占)。  
 
 
 如果不希望 flock() 在锁定时堵塞,则是 LOCK_NB(Windows 上还不支持),即遇到有锁不等待,直接报错返回EWOULDBLOCK
 写法为:$re = flock(lockfd,LOCK_EX|LOCK_NB)
 有错则返回$re = -1,errno = EWOULDBLOCK
fwrite()   int fwrite ( resource $handle , string $string [, int $length ] )
 
 handle
 文件系统指针,是典型地由 fopen() 创建的 resource(资源)。
 string
 The string that is to be written. 
 length
 如果指定了 length,当写入了 length 个字节或者写完了 string 以后,写入就会停止,视乎先碰到哪种情况。 
 
 注意如果给出了 length 参数,则 magic_quotes_runtime 配置选项将被忽略,而 string 中的斜线将不会被抽去。
 
 fwrite() 返回写入的字符数,出现错误时则返回 FALSE 。
fclose()   bool fclose ( resource $handle )
 
 handle
 文件指针必须有效,并且是通过 fopen() 或 fsockopen() 成功打开的。

通常这样子并不能从根本解决阻塞问题,只能是缓解一下,最好是通过中间件或者reids把请求排成一个队列,保证请求队列不会数据丢失,但是对于写入的数据不是那么重要的,可以用这个方法,直接写入,丢失就丢失了。

在前期调试的时候,可以先用这个方法直接把数据写在文件里,可视化强烈一些,后期可以用mongodb替换文件写入,或者多个文件分类分目录写入,而控制阻塞问题需要使用redis等来控制确保单文件操作的同时,请求不会丢失。

相关推荐