2012-11-25 19 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