Skip to main content

PHP Flock Function to Lock File While Reading or Writing

Concurrency is one of the biggest problems in file handling. While you are writing or reading a file someone or some other process may try to write the same file, this situation creates a conflict. To overcome this problem we can use php flock function to lock the file while writing. Once you have finished your operation you can release lock so that now the file will be available for other processes. Acquiring lock is one of the key aspects of file handling in PHP.

PHP Flock Function

PHP Flock() Function

Flock is a built-in function provided by PHP to acquire a different kind of locking while file operation like read, write.

PHP Flock Function Signature:
bool flock($Handle , int $Operation , [int $wouldblock])

Parameters of flock function:

  1. Handle: A file pointer which is created using fopen() function. This is mendatory parameter.
  2. Operation: This is an integer which is to define a kind of lock. You can pass one of the followings:
    1. LOCK_SH: To acquire a shared lock on your file.
    2. LOCK_EX: To acquire an exclusive lock on your file.
    3. LOCK_UN: To release lock both shared or exclusive.
    4. LOCK_NB: To add bit mask if you do not want the flock to block while locking.
  3. Wouldblock: A non-mandatory parameter passed by reference. If it is set to 1 means lock would block.

Returns: PHP Flock function returns true if the lock is acquired otherwise false.

So to lock the file in exclusive mode you can use flock($file_pointer_handle, LOCK _EX).  If you want to take shared lock then you need to just change operation parameter to LOCK_SH.

To unlock the locked file you need to use the same php flock function with parameter LOCK_UN like flock($your_file_pointer, LOCK_UN)

PHP Flock function Example

1. Basic Example
<?php
$fp = fopen(dirname(__FILE__).'/text.txt' ,'w+') or die('Not able to open the file');//Open the file
if(flock($fp, LOCK_EX)){ //Take exclusive lock
fwrite($fp, 'This is test string'); //Write to file
fflush($fp);//Flush the output
flock($fp, LOCK_UN);//release the lock
}
else{
print 'Not able to lock file exclusively';
}
fclose($fp);
?>

In the above example, the code flock($fp, LOCK_EX) is used to get execlusive lock on the file opened by fopen function. Once the file is get locked we are writing to file and flusing the output forcefully so that whatever is at $fp file pointer stream can go to file. And after that we are releasing the lock using flock($fp, LOCK_UN). If you will see closely then you can find that we have used if statement with flock($fp, LOCK_EX), and this is because we are checking if file lock is acquired. If lock is not getting acquired we are not doing any operation.

2 Example with LOCK_NB:
Let us take the same example:
<?php
$fp = fopen(dirname(__FILE__).'/text.txt' ,'w+') or die('Not able to open the file');//Open the file
if(flock($fp, LOCK_EX|LOCK_NB)){ //Take exclusive lock with bit mask
fwrite($fp, 'This is test string 2'); //Write to file
fflush($fp);//Flush the output
flock($fp, LOCK_UN);//release the lock
}
else{
print 'Not able to lock file exclusively';
}
fclose($fp);
?>

What happens if the file is locked?

Let us take below example:
<?php
$fp = fopen(dirname(__FILE__).'/text.txt' ,'w+');
print 'File is opend';
if(flock($fp, LOCK_EX)){
print 'file is locked';
sleep(10);
flock($fp, LOCK_UN);
print 'file lock is released';
}
else{
print 'File is not locked';
}
fclose($fp);
?>

Now run this code simultaneously from 2 browsers(Browser A and Browser B) and see what is happening. In Browser A, PHP flock function will acquire lock and sleep for 10 second. Now the script which you have run from browser B will wait for lock to be released by browser A and then it will take a lock.

To overcome with this situation you can use LOCK_NB. If you will use LOCK_NB then browser B will check for the lock and if lock will not be given then it will come in else condition. Below is the same example with LOCK_NB.
<?php
$fp = fopen(dirname(__FILE__).'/text.txt' ,'w+');
print 'File is opend';
if(flock($fp, LOCK_EX|LOCK_NB)){
print 'file is locked';
sleep(10);
flock($fp, LOCK_UN);
print 'file lock is released';
}
else{
print 'File is not locked';
}
fclose($fp);
?>

So now if you will run the above code from 2 browser simultaneously then first will take lock and wait for 10 second, but in second browser the control will go into else condition and print “file is not locked.”

Shared lock using Flock

In the above examples, we have used LOCK_EX and acquired the exclusive lock. Now, what’s the shared lock?

A shared lock is commonly known as the reader lock where the lock can be acquired simultaneously by more than one process. So in the case of the read operation, we can use LOCK_SH where multiple processes can acquire the lock at the same time.

So if you will use the same above example of sleep(10) with the shared lock then both process will work simultaneously.

<?php
$fp = fopen(dirname(__FILE__).'/text.txt' ,'r');
print 'File is opend';
if(flock($fp, LOCK_SH)){
print 'file is locked';
sleep(10);
flock($fp, LOCK_UN);
print 'file lock is released';
}
else{
print 'File is not locked';
}
fclose($fp);
?>

Key Point with PHP flock() function

  1. Flock function does not work FAT file system because flock is supported on antiquated file system. So if you have FAT or its derivative filesytem then flock will always return false value.
  2. Since flock always accept file pointer handle created by fopen, if you will change the $fp or your handle variable then lock will be immediately released.
  3. Flock function performs the locking on the process level, means lock is acquired by one process at a time. So if you will use multithreaded server API like ISAPI then you should not rely on fopen to protect against another php script to open or write to the file.
  4. PHP flock function uses advisory locking, not a mendatory locking. But on Windows OS it uses mandatory locking.

PHP flock on Network File System(NFS)

Practically can you can not lock the file using php flock function if the file is on the NFS because the file will be shared and mapped on another computer too. If other systems also want to do the operation on the same file at the same time then you should not rely on flock.

Solution?
Use Memcache and put a lock variable in the Memcache with the key as file name. Now on all system where the file is mapped and read-write operation is required, just check the Memcache variable before opening the file.

 

 

Support Me by Sharing This Article

Ankur Kumar Singh

I am a PHP programmer having some knowledge about Linux. I am always interested in web development and knowledge sharing. I am full time tech evangelist part time human being. :-)

Leave a comment/Ask Question

shares