使用PHP文件锁写一个多个请求同时并发写入一个文件,要求不脏读、数据不丢失.

//并发文件操作
function filehandle($filename,$data){
$start = 0;
$end = 3000; if(!file_exists($filename)){
return "文件不存在";
} if(!is_string($data)){
return "写入内容只能为字符串类型";
} if($fp = fopen($filename,'a')){
do{
//获取文件独占锁
$canWrite = flock($fp,LOCK_EX); if(!$canWrite){
$rand = mt_rand(1,100);
//让程序休眠随机毫秒数再试
usleep($rand*1000);
$start += $rand;
} }while(!$canWrite && $start < $end); if(!$canWrite){
//未能获得锁
return "获取文件锁失败";
}else{
fwrite($fp,$data);
} //释放锁定,关闭文件
flock($fp, LOCK_UN);
fclose($fp);
return true; }else{
return "打开文件失败";
} }

此方法的要点是当用户操作文件的时候必须获取文件的独占锁,若文件已经被锁定,则让程序休眠若干毫秒后重试,知道获得锁或者超时为止。

flock():轻便的咨询文件锁定

函数参数说明:

handle - 文件系统指针,是典型地由 fopen() 创建的 resource(资源)。

operation - 可以是以下值之一:

  1. LOCK_SH 取得共享锁定(读取的程序)。
  2. LOCK_EX   取得独占锁定(写入的程序。
  3. LOCK_UN 释放锁定(无论共享或独占)。

返回值:成功时返回 TRUE, 或者在失败时返回 FALSE

方案二:

file_put_contents($filename, $data, FILE_APPEND|LOCK_EX);

int file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] );

函数说明:将一个字符串写入文件

参数说明:

filename - 要被写入数据的文件名。

data - 要写入的数据。类型可以是 string,array(一维) 或者是 stream 资源。

flags - flags的值可以是 以下 flag 使用 OR (|) 运算符进行的组合。

FILE_USE_INCLUDE_PATH : 在 include 目录里搜索 filename。 更多信息可参见 include_path。
    FILE_APPEND : 如果文件 filename 已经存在,追加数据而不是覆盖。
    LOCK_EX : 在写入时获得一个独占锁。

context - 一个 context 资源。

返回值:该函数将返回写入到文件内数据的字节数,失败时返回FALSE

(注:以上方案均未经过实际项目测试)

使用PHP文件锁写一个多个请求同时并发写入一个文件,要求不脏读、数据不丢失的更多相关文章

  1. 对tomcat来说,每一个进来的请求(request)都需要一个线程,直到该请求结束。

    这段时间折腾了哈java web应用的压力测试,部署容器是tomcat 7.期间学到了蛮多散碎的知识点,及时梳理总结,构建良好且易理解的知识架构把它们组织起来,以备忘.对web应用开发者来说,我们很关 ...

  2. 一个封装HTTP请求的函数(C++)

    这里封装了HTTP请求的,支持GET与POST,并支持各种参数组合,调用方式很简单使用DEVWEB::WebRequest(string(“http://www.luaie.com/”),ret);就 ...

  3. 接口测试入门(2)--get和post初级请求/使用httpclient做一个获取信息list的请求(需要登录才可以)

    抛去测试自动化的架构来,直接写单个测试用例的思路如下: 1.获取测试case的接口,对每一个接口的请求方式(get/post/delete/put)进行分析,是否需要参数(不同的用例设置不同的参数,如 ...

  4. springMVC一个Controller处理所有用户请求的并发问题(转)

    springMVC一个Controller处理所有用户请求的并发问题 有状态和无状态的对象基本概念: 有状态对象(Stateful Bean),就是有实例变量的对象 ,可以保存数据,是非线程安全的.一 ...

  5. jsp页面:一个form,不同请求提交form

    需求:一个表单中有一个请求 action="url"发送数据地址: 在表单外有一个请求,请求form表单提交的数据 我们用js来写:通过每次请求传不同的action=url; 例如 ...

  6. 怎样使用ListView实现一个带有网络请求,解析,分页,缓存的公共的List页面来大大的提高工作效率

    在寻常的开发中常常会有非常多列表页面.每做一个列表页就须要创建这个布局文件那个Adapter适配器文件等等一大堆与之相关的附属的不必要的冗余文件. 假设版本号更新迭代比較频繁,如此以往,就会使项目pr ...

  7. Asp.Net MVC是否针对每次请求都重新创建一个控制器实例

    一.Asp.Net MVC是否针对每次请求都重新创建一个控制器实例 默认情况下,答案是确定的. ControllerBuilder类 ControllerBuilder.Current用户获取默认的控 ...

  8. 一个跨域请求的XSS续

    之前讨论过,在解决post跨域请求时,采用iframe+本域代理页的形式,兼容性(当然是包括IE6啦)是最好的.上次提到,代理页面的作用是:执行本域下的回调函数.就是这个原因,给XSS带来了便利.详细 ...

  9. 利用生产者消费者模型和MQ模型写一个自己的日志系统-并发设计里一定会用到的手段

    一:前言 写这个程序主要是用来理解生产者消费者模型,以及通过这个Demo来理解Redis的单线程取原子任务是怎么实现的和巩固一下并发相关的知识:这个虽然是个Demo,但是只要稍加改下Appender部 ...

随机推荐

  1. asp.net(C#)html无限分类树 可新增 删除 修改

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="ProductSort.aspx ...

  2. 【转载】Retina屏的移动设备如何实现真正1px的线?

    文章转载自 酷勤网 http://www.kuqin.com/ 原文链接:http://www.kuqin.com/shuoit/20150530/346322.html 原文摘要:前些日子总被人问起 ...

  3. java学习笔记(一) 服务器的认识

    RPC与RMI.SOAP的联系及区别 http://www.jb51.net/article/68971.htm 几大服务器的区别nginx/tomcat/ http://www.cnblogs.co ...

  4. Java IO(IO流)-2

    IO流 第一部分 (OutputStreamWriter BufferOutputStream) 转换流 超类为Reader和Writer 是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流 ...

  5. 【转】open参数O_DIRECT的学习

    open参数O_DIRECT的学习 使用 O_DIRECT 需要注意的地方 posix_memalign详细解释 free:这里好几个方法我都没测试成功,最后还是用posix_memalign 对齐的 ...

  6. LeetCode 16. 3Sum Closest. (最接近的三数之和)

    Given an array S of n integers, find three integers in S such that the sum is closest to a given num ...

  7. [Bayesian] “我是bayesian我怕谁”系列 - Exact Inferences

    要整理这部分内容,一开始我是拒绝的.欣赏贝叶斯的人本就不多,这部分过后恐怕就要成为“从入门到放弃”系列. 但,这部分是基础,不管是Professor Daphne Koller,还是统计学习经典,都有 ...

  8. Web设计新手应知道的10个锦囊妙计

    摘要:你在网页设计所学到的大多数教训都来自工作经验.学习是一个反复持续的过程,并且没有比犯错更好的方式来获得知识.在本文中,我们将讨论10个重要并常规的技巧,这是每位Web设计师新手都应该知道. 在做 ...

  9. java自动化-juint框架简述

    本人使用的是java的juint框架来组织的自动化测试,故我这边需要简单介绍一下juint框架 首先,建议自行百度一下juint框架,先有一个大概的了解 所谓的接口自动化测试,会对多个接口中每一个接口 ...

  10. 工具:Entity Framework Profiler

    使用方式: 1.项目中添加引用:EntityFrameworkProfiler.Appender 2.应用程序启动方法中添加下面一行代码: HibernatingRhinos.Profiler.App ...