flock

Applies or releases an advisory shared or exclusive lock on an open file handle.

Signature
flock(resource $stream, int $operation, int &$would_block = null): bool
  • Added in PHP 4.0.0

Parameters

ParameterTypeDescription
$streamresourceAn open file pointer, normally from fopen().
$operationintLOCK_SH for a shared (read) lock, LOCK_EX for an exclusive (write) lock, or LOCK_UN to release. Bitwise-OR with LOCK_NB to make the call non-blocking.
$would_blockoptionalint= nullSet to 1 by reference if the lock would have blocked, which only happens when LOCK_NB is used.

Return value

booltrue on success, false on failure.

Errors

Emits an E_WARNING if the stream is not a valid file pointer; throws a TypeError if a non-resource is passed.

flock is how you stop two PHP processes from trampling each other while writing the same file. It takes a lock on an open handle, not on a path, so you always call fopen first.

Shared versus exclusive

LOCK_SH lets many readers hold the lock at once but blocks any writer. LOCK_EX allows exactly one holder. By default the call blocks until the lock is available; add LOCK_NB to return immediately instead, and inspect the third argument to learn whether it would have blocked.

When to reach for it

  • A counter or aggregate file that several requests increment.
  • A cron job that must not run twice — take LOCK_EX | LOCK_NB on a lockfile and exit if it fails.
  • Appending to a shared log without interleaved lines.

What trips people up

On Unix the locks are advisory: a process that never calls flock can read and write the file freely, so the lock only coordinates code that agrees to participate. Windows is the exception — there flock uses mandatory locking, which the operating system enforces against every process. It also does not work reliably over NFS, and on FAT and similar filesystems it always returns false.

Opening with mode 'w' truncates the file before you get the chance to lock it, which defeats the purpose. Use 'c' or 'c+', which create without truncating, then lock, then ftruncate and rewind yourself.

The lock is released when you call LOCK_UN or when the handle is closed — including when the script ends.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Increment a hit counter file safely from multiple simultaneous requests.
  • Guard a cron script with LOCK_EX | LOCK_NB so a slow run is never started twice.
  • Serialize appends to a shared audit log across worker processes.

Frequently asked questions

Does flock prevent other processes from reading the file?

On Unix, no — flock is advisory there, so it only blocks processes that also call `flock` on the same file, and anything reading or writing directly is unaffected. Windows is the exception: PHP uses mandatory locking there, so the operating system enforces the lock against every process. (Mandatory locking is also possible on Linux and System V systems for files with the setgid bit set and the group-execute bit cleared, on a filesystem mounted with `mand`.)

What is the difference between LOCK_SH and LOCK_EX?

LOCK_SH is a shared read lock that many processes can hold simultaneously, while LOCK_EX is exclusive and only one process can hold it. A LOCK_EX request waits until every shared lock has been released.

Do I need to call flock with LOCK_UN before fclose?

No, closing the handle releases the lock, and so does the script ending. An explicit LOCK_UN is still good practice when the handle stays open for further work.

More examples

Non-blocking lock as a single-instance guard

Nothing else holds the lock here, so the first branch runs. In a real deployment a second concurrent process falls into the else branch immediately instead of waiting, with `$wouldBlock` set to 1.

Example · php
<?php
$lock = fopen('job.lock', 'c');

if (flock($lock, LOCK_EX | LOCK_NB, $wouldBlock)) {
    echo "got the lock, running the job\n";
    flock($lock, LOCK_UN);
} else {
    echo "another run is in progress (would_block=$wouldBlock)\n";
}

fclose($lock);
unlink('job.lock');

A shared lock lets readers coexist

Both calls return `true` because LOCK_SH is shared — any number of readers can hold it at once. An LOCK_EX request would have to wait for all of them to release.

Example · php
<?php
file_put_contents('shared.txt', "stable data\n");

$a = fopen('shared.txt', 'r');
$b = fopen('shared.txt', 'r');

var_dump(flock($a, LOCK_SH));   // first reader
var_dump(flock($b, LOCK_SH));   // second reader, also succeeds

flock($a, LOCK_UN);
flock($b, LOCK_UN);
fclose($a);
fclose($b);
unlink('shared.txt');

Locks are advisory, not enforced

The exclusive lock is held, yet `file_get_contents` still reads the file and prints its contents. Every process that touches the file must call `flock` for the coordination to mean anything.

Example · php
<?php
file_put_contents('advisory.txt', 'locked content');

$fh = fopen('advisory.txt', 'c+');
flock($fh, LOCK_EX);

// A caller that never asks for a lock is not blocked at all
echo "unlocked read: ", file_get_contents('advisory.txt'), "\n";

flock($fh, LOCK_UN);
fclose($fh);
unlink('advisory.txt');

Discussion

  • Be the first to comment on this lesson.