2012-11-25 16 views
1

我在PHP中有一个操作,用于检查具有ID的对象是否在DB中,如果不是,则创建一个条目。对同一个ID的请求可能会同时发生,所以我想阻止该ID被插入两次。在PHP中删除最后一个sem_release后的信号量

我目前使用下面的代码来锁定/解锁访问数据库的特定关键:由于我创造的每个对象ID的个人旗语:

$semaphore = sem_get($keyForID, 1); 

sem_acquire($semaphore); 

// 1.) check for id 
// 2.) insert object if it doesn't exist 

sem_release($semaphore); 

我的问题是,我是否明确地必须使用sem_remove删除这些信号量还是PHP在sem_release之后自动执行这些信号量?

如果我必须明确地删除信号量,有没有一种简单可靠的方法来检查该信号是否被另一个线程获取,以便后者不会在sem_release上崩溃?想到使用共享内存,但这需要另一个信号量来读/写线程数。

回答

2

sem_remove明确销毁给定的信号量,这将使其无法用于任何其他正在运行的进程或线程的进一步计算,直到使用sem_get重新创建它为止。例如,如果3个进程试图访问相同的信号量(只有1个并发访问),并且第一个进程在另外两个进程获得它之前就销毁它,则后两个进程可能最终同时运行,而不是按顺序如预期)。

你真的不想打电话sem_remove,除非你知道所有其他正在运行的进程不再使用它。

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