五月综合缴情婷婷六月,色94色欧美sute亚洲线路二,日韩制服国产精品一区,色噜噜一区二区三区,香港三级午夜理伦三级三

您現(xiàn)在的位置: 365建站網(wǎng) > 365文章 > 在PHP中通過系統(tǒng)信號量加鎖方式獲取遞增序列ID

在PHP中通過系統(tǒng)信號量加鎖方式獲取遞增序列ID

文章來源:365jz.com     點擊數(shù):235    更新時間:2009-09-26 11:42   參與評論

 前一陣子,設(shè)計LAJP時需要在PHP中生成唯一ID,看似小菜一碟卻著實讓我為難了,在Java中一個同步方法即可搞定的事,但在PHP中卻沒有好的解決思路。

在網(wǎng)上搜了搜,有兩個辦法但都不太好:一個是簡單的以進(jìn)程ID+時間戳,或進(jìn)程ID+隨機(jī)數(shù)來產(chǎn)生近似的唯一ID,雖簡單但對于追求“完美”的我不愿這樣湊合,再說Apache2以后進(jìn)程會維持相當(dāng)長得時間,生成的ID發(fā)生碰撞的幾率還是比較大的;第二個思路是通過Mysql的自增字段,這個就更不能考慮了,效率低不說,我的設(shè)計里壓根就沒數(shù)據(jù)庫。

遞增ID的獲取是個過程:

   1. 從全局某個存儲中讀取ID
   2. 給ID加1
   3. 將ID重新存入全局存儲

在多進(jìn)程或線程的程序中需要將上述3步作為單步的原子操作,才能保證ID的唯一。

Java中很好解決,這是因為Java程序大多以多線程方式運行,每個線程都能共享Java進(jìn)程中的變量,并能方便的加線程鎖控制線程的運轉(zhuǎn)同步。在PHP中ID全局存儲沒問題,可以放在session中,大不了放在文件中,但進(jìn)程間同步就是問題了。

實際上進(jìn)程調(diào)度、管理是操作系統(tǒng)內(nèi)核必須實現(xiàn)的功能,今天介紹的信號量(也稱為信號燈)就是在Unix/Linux上解決進(jìn)程同步的一項技術(shù)。

信號燈原是用在鐵路上的管理機(jī)制,我們今天看到的鐵路大多是雙線并行,但有的路段受山勢、地形影響只有單條鐵軌,必須保證同一時間只能有一列火車運行通過這些路段。早先鐵路上就是用信號燈來管理的:沒有火車經(jīng)過時,信號等處于閑置狀態(tài),一旦有火車進(jìn)入此路段,信號燈即變?yōu)樵谟脿顟B(tài),其他的火車經(jīng)過時就需要等待,等待先前的火車駛出路段信號等變?yōu)殚e置后,才能進(jìn)入此路段,一旦又有火車進(jìn)入,信號燈又變?yōu)榉泵?.....,以此來保障鐵路運行的安全暢通。

Unix系統(tǒng)就像鐵路管理局控制信號燈一樣管理控制信號量的狀態(tài),因此也可以這樣說信號量是由內(nèi)核管理的,信號量不僅能控制進(jìn)程間的同步,同樣可以控制線程間的同步。

信號量屬于系統(tǒng)進(jìn)程間通訊技術(shù)(IPC),今天我們只從PHP角度介紹信號量的使用,有關(guān)IPC的技術(shù)細(xì)節(jié)可參考Stevens的權(quán)威著作《UNIX網(wǎng)絡(luò)編程第二卷 進(jìn)程間通信》。

先看最終的代碼:
001    <?php
002
003    // ---------------------------------------------------
004    // 遞增序列號ID(1~1000000000)
005    //
006    // ID存儲在共享內(nèi)存中(shared memory),通過信號燈(semaphore)同步
007    // ---------------------------------------------------
008
009    $IPC_KEY = 0x1234;   //System V IPC KEY
010    $SEQ_KEY = "SEQ";    //共享內(nèi)存中存儲序列號ID的KEY
011
012    //創(chuàng)建或獲得一個現(xiàn)有的,以"1234"為KEY的信號量
013    $sem_id = sem_get($IPC_KEY);
014    //創(chuàng)建或關(guān)聯(lián)一個現(xiàn)有的,以"1234"為KEY的共享內(nèi)存
015    $shm_id = shm_attach($IPC_KEY, 64);
016
017    //占有信號量,相當(dāng)于上鎖,同一時間內(nèi)只有一個流程運行此段代碼
018    sem_acquire($sem_id);
019
020    //從共享內(nèi)存中獲得序列號ID
021    $id = @shm_get_var($shm_id, $SEQ_KEY);
022    if ($id == NULL || $id >= 1000000000)
023    {
024        $id = 1;
025    }
026    else
027    {
028        $id++;
029    }
030    //將"++"后的ID寫入共享內(nèi)存
031    shm_put_var($shm_id, $SEQ_KEY, $id);
032
033    //釋放信號量,相當(dāng)于解鎖
034    sem_release($sem_id);
035    //關(guān)閉共享內(nèi)存關(guān)聯(lián)
036    shm_detach($shm_id);
037
038    echo "序列號ID:{$id}";
039    ?>

009行,定義了一個16進(jìn)制的整形KEY,在PHP中只支持System V的IPC機(jī)制,需要通過一個KEY關(guān)聯(lián)到指定的資源(消息隊列、信號量、共享內(nèi)存)。
010 行,定義了一個在共享內(nèi)存中存儲遞增ID的KEY,這是PHP對System V共享內(nèi)存的閑置:需要通過類似hashtable的KEY-VALUE方式存儲變量。在上面的代碼中使用共享內(nèi)存做ID的存儲容器,也可以換為 Session、文件等其他機(jī)制,本文重點是信號量,有關(guān)共享內(nèi)存的知識以后在講(別忘了前面推薦的那本書)。
013行,獲得系統(tǒng)中的以1234為KEY的信號量,如果系統(tǒng)中沒有就創(chuàng)建一個。
015行,同13行相似,獲得系統(tǒng)中的以1234為KEY的共享內(nèi)存,如果系統(tǒng)中沒有就創(chuàng)建一個,第二個參數(shù)64表示創(chuàng)建64bytes大小的共享內(nèi)存。
018~034 行,同步代碼區(qū),當(dāng)一個進(jìn)程或線程執(zhí)行sem_acquire函數(shù)占有了信號量,到它調(diào)用sem_release函數(shù)釋放信號量的過程內(nèi),其他進(jìn)程或線程執(zhí)行到sem_acquire會阻塞。021行從共享內(nèi)存中獲得ID,函數(shù)shm_get_var前綴"@"是為了屏蔽出錯信息(第一次執(zhí)行時,共享內(nèi)存中并沒有以"SEQ"為KEY的數(shù)據(jù),會在頁面上打印警告信息)。
其他語句非常簡單,不需多講。

程序編好后,訪問這個PHP頁面,會遞增的輸出數(shù)字。

我們可以通過系統(tǒng)命令ipcs查看在程序創(chuàng)建的信號量和共享內(nèi)存:

$ ipcs

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00001234 1212443    www-data  666        64         0        

------ Semaphore Arrays --------
key        semid      owner      perms      nsems    
0x00001234 163841     www-data  666        3       

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages

前兩段分別是共享內(nèi)存和信號量,0x00001234既是我們創(chuàng)建的KEY。

也可以通過命令ipcrm刪除:

$ ipcrm -M 0x00001234         #刪除共享內(nèi)存
$ ipcrm -S 0x00001234         #刪除信號量

---------------------------------------------

PHP手冊中關(guān)于IPC的資料非常少,這點也不難想象,Stevens已經(jīng)在十幾年前講得透透的東東,在PHP中只是包裝了一下,還有多少必要去深入說明呢?
文本只是借著ID說了說信號量的使用,如果您有更簡單的生成自增ID的辦法,還望賜教。
可能有朋友還想了解信號量的執(zhí)行效率,我這里用一句過時的流行語總結(jié): 相當(dāng)?shù)目臁?br />

如對本文有疑問,請?zhí)峤坏浇涣髡搲瑥V大熱心網(wǎng)友會為你解答??! 點擊進(jìn)入論壇

發(fā)表評論 (235人查看,0條評論)
請自覺遵守互聯(lián)網(wǎng)相關(guān)的政策法規(guī),嚴(yán)禁發(fā)布色情、暴力、反動的言論。
昵稱:
最新評論
------分隔線----------------------------

其它欄目

· 建站教程
· 365學(xué)習(xí)

業(yè)務(wù)咨詢

· 技術(shù)支持
· 服務(wù)時間:9:00-18:00
365建站網(wǎng)二維碼

Powered by 365建站網(wǎng) RSS地圖 HTML地圖

copyright © 2013-2024 版權(quán)所有 鄂ICP備17013400號