I have an operation in PHP that checks if an object with an ID is in a DB and creates an entry for it if it isn’t. A request for the same ID can happen concurrently, so I want to prevent the ID from being inserted twice.
I am currently using the following code to lock/unlock access to the DB for that particular key:
$semaphore = sem_get($keyForID, 1);
sem_acquire($semaphore);
// 1.) check for id
// 2.) insert object if it doesn't exist
sem_release($semaphore);
My question is: Since I’m creating an individual semaphore for every object-ID, do I explicitly have to remove those semaphores with sem_remove or does PHP do that automatically after sem_release?
If I do have to remove the semaphore explicitly, is there an easy and reliable way of checking if that semaphore is currently acquired by another thread so that latter doesn’t crash on sem_release? Using shared memory comes to mind, but that would require yet another semaphore to read/write the number of threads.
sem_removeexplicitly destroy a given semaphore, which will make it unavailable for further computation for any other running process or thread, until it is recreated usingsem_get. For instance, if 3 processes are trying to access the same semaphore (with only 1 concurrent access), and the first one destroy it before the two others manage to acquire it, the two latter processes may end up running concurrently, instead of sequentially (as expected).You really don’t want to call
sem_remove, unless you know that all other running processes won’t use it anymore.Anyway, in your situation, I would recommend relying on the DB itself for concurrent accessing. If you need to have only one entry created in your DB, use transactions. If you are using a DB which isn’t supporting transactions such as the MyISAM engine on MySQL, either switch to an engine supporting transactions, or in the specific case of MyISAM, try using atomic operations.