1

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.

4

1 回答 1

4

sem_remove显式销毁给定的信号量,这将使其无法用于任何其他正在运行的进程或线程的进一步计算,直到使用sem_get. 例如,如果 3 个进程试图访问同一个信号量(只有 1 个并发访问),并且第一个进程在其他两个进程设法获取它之前将其销毁,则后两个进程可能最终并发运行,而不是顺序运行(正如预期的那样)。

您真的不想调用sem_remove,除非您知道所有其他正在运行的进程将不再使用它。

无论如何,在您的情况下,我建议您依靠数据库本身进行并发访问。如果您只需要在数据库中创建一个条目,请使用事务。如果您使用的数据库不支持事务,例如 MySQL 上的 MyISAM 引擎,请切换到支持事务的引擎,或者在 MyISAM 的特定情况下,尝试使用原子操作

于 2012-11-26T09:16:04.980 回答