<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>潘锦的空间 &#187; 多进程</title>
	<atom:link href="https://www.phppan.com/tag/%e5%a4%9a%e8%bf%9b%e7%a8%8b/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sat, 25 Apr 2026 00:56:17 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>锁机制之PHP文件锁</title>
		<link>https://www.phppan.com/2012/08/php-lock/</link>
		<comments>https://www.phppan.com/2012/08/php-lock/#comments</comments>
		<pubDate>Mon, 13 Aug 2012 01:55:56 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[多进程]]></category>
		<category><![CDATA[并发]]></category>
		<category><![CDATA[文件锁]]></category>
		<category><![CDATA[锁机制]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1734</guid>
		<description><![CDATA[锁机制之PHP文件锁 锁机制之所以存在是因为并发导致的资源竞争，为了确保操作的有效性和完整性，可以通过锁机制将 [&#8230;]]]></description>
				<content:encoded><![CDATA[<h1>锁机制之PHP文件锁</h1>
<p>锁机制之所以存在是因为并发导致的资源竞争，为了确保操作的有效性和完整性，可以通过锁机制将并发状态转换成串行状态。作为锁机制中的一种，PHP的文件锁也是为了应对资源竞争。假设一个应用场景，在存在较大并发的情况下，通过fwrite向文件尾部多次有序的写入数据，不加锁的情况下会发生什么？多次有序的写入操作相当于一个事务，我们此时需要保证这个事务的完整性。</p>
<p>如下代码简单模拟了这种事务并发状态： process1.php</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;">&nbsp;
    <span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #000088;">$num</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">100</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$filename</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;processdata.txt&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$fp</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fopen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$filename</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;a&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$num</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #990000;">fwrite</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fp</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;process1: &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #990000;">usleep</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">100000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #990000;">fclose</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fp</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>我们需要先执行第一个事务，在processdata.txt文件中写入这100行。</p>
<p>process2.php</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;">   <span style="color: #000000; font-weight: bold;">&lt;?php</span>
    <span style="color: #000088;">$num</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">100</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$filename</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;processdata.txt&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$fp</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fopen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$filename</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;a&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #000088;">$num</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #990000;">fwrite</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fp</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;process2: &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #990000;">usleep</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">100000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #990000;">fclose</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fp</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>第二个事务，继续向processdata.txt文件中写入100行。</p>
<p>多次同时执行，虽然都写了100行，但是事务1和事务2的数据交错写入，这并不是我们想要的结果。我们要的是事务完整的执行，此时我们需要有个机制去保证在第一个事务执行完后再执行第二个。在PHP中，flock函数完成了这一使命。在事物1和事务2的循环前面都加上：  flock($fp, LOCK_EX); 就能满足我们的需求，将两个事务串行。</p>
<p>当某一个事务执行完flock时，因为我们在这里添加的是LOCK_EX（独占锁定），所以所有对资源的操作都会被阻塞，只有当事务执行完成后，后面的事务才会执行。我们可以通过输出当前的时间的方法来确认这一点。</p>
<p>关于在尾部追加写入，在unix系统的早期版本中存在一个并发写入的问题，如果要在尾部追加，需要先lseek位置，再write。当多个进程同时操作时，会因为并发导致的覆盖写入的问题，即两个进程同时获取尾部的偏移后，先后执行write操作，后面的操作会将前面的操作覆盖。这个问题在后面以添加打开时的O_APPEND操作而得到解决，它将查找和写入操作变成了一个原子操作。</p>
<p>在PHP的fopen函数的实现中，如果我们使用a参数在文件的尾部追加内容，其调用open函数中oflag参数为 O_CREAT|O_APPEND，即我们使用追加操作不用担心并发追加写入的问题。</p>
<p>在PHP的session默认存储实现中也用到了flock文件锁，当session开始时就调用PS_READ_FUNC，且以O_CREAT | O_RDWR  | O_BINARY  打开session数据文件，此时会调用flock加上写锁，如果此时有其它进程访问此文件（即同一用户再次发起对当前文件的请求），就会显示页面加载中，进程被阻塞了。加写锁其出发点是为了保证此次会话中对session的操作事务能完整的执行，防止其它进程的干扰，保证数据的一致性。如果一个页面没有session修改操作，可以尽早的调用session_write_close()释放锁。</p>
<p>文件锁是针对文件的锁，除了这种释义，还可以理解为用文件作为锁。在实际工作中，有时为确保单个进程的执行，我们会在程序执行前判断文件是否存在，如果不存在则创建一个空文件，在进程结束后删除这个空文件，如果存在，则不执行。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2012/08/php-lock/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
