开发者

Synchronized functions in PHP

开发者 https://www.devze.com 2023-02-01 18:55 出处:网络
Is there a way to make functions i开发者_如何学Gon PHP synchronized to make sure that two or more webusers can\'t execute the same function at the same time?I think you might achieve the same(if avail

Is there a way to make functions i开发者_如何学Gon PHP synchronized to make sure that two or more webusers can't execute the same function at the same time?


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.


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.


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.


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.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号