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

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

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

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

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

原文地址:https://www.cnblogs.com/online-link/p/6091236.html