Is there a way to make functions in PHP synchronized to make sure that two or more webusers can't execute the same function at the same time?
-
1I think you need to provide a bit more information here. Is the function you are trying to execute not thread safe? – sberry Dec 28 '10 at 21:42
-
1This thread is a bit old but I think this is a pretty good answer: [Stackoverflow](http://stackoverflow.com/questions/4710869/php-threads-and-synchronization) – Nicsoft Nov 19 '12 at 09:45
6 Answers
I think you might achieve the same(if available) by using sem_acquire to acquire a semaphore (entering crital section) and sem_release to release the lock.

- 60,935
- 33
- 147
- 186
-
6sem_acquire and sem_release are not available by default and they are not available on Windows http://www.php.net/manual/en/intro.sem.php – Lukasz Dec 28 '10 at 22:06
You can use external locking - for example, file locking via flock. Create a file somewhere and have script lock it. You can also use semaphores, but those are Unix only.

- 10,593
- 6
- 56
- 103
-
I like this answer. [Here](https://stackoverflow.com/questions/38804404/synchronized-block-in-php-7/52249188#52249188) is an example of the "flock" method. – mevdschee Sep 10 '18 at 00:39
I can't think of any problem that you might be facing. However, I once had to write a PHP script that was doing some complex computations and I had to make sure that it wasn't executed simultaneously by two users. To accomplish that I created an empty file on the start of the script and deleted it when the computations were completed. Of course, the script checked if the file existed before it started computations.

- 7,572
- 4
- 41
- 50
-
1
-
1consider this: prcess 1 cecks i the file exists and it does not exists. Then proccess ones timesclice ends and it is process twos turn it checks if te ile exists and because pocess two has not yet created it.both proccesses wil run at the sametime! Your solution reduces the risk but it does not eliminate it. You sould use sem_aquire as Alfred suggested. – Oliver A. Dec 28 '10 at 21:57
-
@Oliver A.: Please keep in mind that I've only described the solution used by me some long time ago. I haven't said that this is the best one. – Lukasz Dec 28 '10 at 22:04
-
1Baran. I never meant to attack/insult you. I just wanted to point out that this is not as save as it may sound. – Oliver A. Dec 29 '10 at 06:04
Note that local file locking and semaphores only works if you have one web server. If your script is hosted by multiple load-balanced servers you will have to find some other locking mechanism, for example a specialised "locking server" on one machine or some sort of file locking over NFS.

- 90,431
- 16
- 141
- 175
In the past, I have created simple locks on records in the database. If you are processing an existing record, you can store its type, id, and the time of the lock. Make sure the type and id are the key of the database table (or of the cache). When you start the process, you acquire the lock in a way that will not erase an existing lock. If there is an expired lock, take it. If there is an existing lock that has not expired, fail to start the process (either queue or return). If there was no lock, or there was an existing expired lock, you are golden. You now have the lock. When you are done, release the lock.
You can tie this kind of system to records already in your database, create new tables for work in progress, or even use an external cache.

- 19,824
- 17
- 99
- 186

- 4,063
- 1
- 21
- 23
Some more details on why you need the lock would be nice. If you're having problems with users' database interactions clobbering each other, you should be looking at using transactions in your database code so that complex changes are processed atomically by the database.
As an example: I use Symfony with the Doctrine ORM, so my commit code usually looks something like this:
$conn = Doctrine_Manager::connection();
$conn->beginTransaction();
try {
// .. database code ..
$conn->commit();
} catch(Doctrine_Exception $ex) {
$conn->rollback();
// additional exception handling
}
Now, this won't keep users from clobbering each other if they happen to be modifying the same record at the same time; however, it will make sure that the database stays consistent--that is, either User A's changes take effect or user B's changes take effect, but never a hodge-podge of User A and User B's changes depending on the mood of the DB.

- 2,360
- 13
- 17