天天躁日日躁狠狠躁AV麻豆-天天躁人人躁人人躁狂躁-天天澡夜夜澡人人澡-天天影视香色欲综合网-国产成人女人在线视频观看-国产成人女人视频在线观看

PHP下通過系統信號量加鎖方式獲取遞增序列ID

在網上搜了搜,有兩個辦法但都不太好:一個是簡單的以進程ID+時間戳,或進程ID+隨機數來產生近似的唯一ID,雖簡單但對于追求“完美”的我不愿這樣湊合,再說Apache2以后進程會維持相當長得時間,生成的ID發生碰撞的幾率還是比較大的;第二個思路是通過Mysql的自增字段,這個就更不能考慮了,效率低不說,我的設計里壓根就沒數據庫。
遞增ID的獲取是個過程:
1. 從全局某個存儲中讀取ID
2. 給ID加1
3. 將ID重新存入全局存儲
在多進程或線程的程序中需要將上述3步作為單步的原子操作,才能保證ID的唯一。
Java中很好解決,這是因為Java程序大多以多線程方式運行,每個線程都能共享Java進程中的變量,并能方便的加線程鎖控制線程的運轉同步。在php中ID全局存儲沒問題,可以放在session中,大不了放在文件中,但進程間同步就是問題了。
實際上進程調度、管理是操作系統內核必須實現的功能,今天介紹的信號量(也稱為信號燈)就是在Unix/Linux上解決進程同步的一項技術。
信號燈原是用在鐵路上的管理機制,我們今天看到的鐵路大多是雙線并行,但有的路段受山勢、地形影響只有單條鐵軌,必須保證同一時間只能有一列火車運行通過這些路段。早先鐵路上就是用信號燈來管理的:沒有火車經過時,信號等處于閑置狀態,一旦有火車進入此路段,信號燈即變為在用狀態,其他的火車經過時就需要等待,等待先前的火車駛出路段信號等變為閑置后,才能進入此路段,一旦又有火車進入,信號燈又變為繁忙......,以此來保障鐵路運行的安全暢通。
Unix系統就像鐵路管理局控制信號燈一樣管理控制信號量的狀態,因此也可以這樣說信號量是由內核管理的,信號量不僅能控制進程間的同步,同樣可以控制線程間的同步。
信號量屬于系統進程間通訊技術(IPC),今天我們只從php角度介紹信號量的使用,有關IPC的技術細節可參考Stevens的權威著作《UNIX網絡編程第二卷 進程間通信》。
先看最終的代碼:
復制代碼 代碼如下:
<?php
// ---------------------------------------------------
// 遞增序列號ID(1~1000000000)
//
// ID存儲在共享內存中(shared memory),通過信號燈(semaphore)同步
// ---------------------------------------------------
$IPC_KEY = 0x1234; //System V IPC KEY
$SEQ_KEY = "SEQ"; //共享內存中存儲序列號ID的KEY
//創建或獲得一個現有的,以"1234"為KEY的信號量
$sem_id = sem_get($IPC_KEY);
//創建或關聯一個現有的,以"1234"為KEY的共享內存
$shm_id = shm_attach($IPC_KEY, 64);
//占有信號量,相當于上鎖,同一時間內只有一個流程運行此段代碼
sem_acquire($sem_id);
//從共享內存中獲得序列號ID
$id = @shm_get_var($shm_id, $SEQ_KEY);
if ($id == NULL || $id >= 1000000000)
{
$id = 1;
}
else
{
$id++;
}
//將"++"后的ID寫入共享內存
shm_put_var($shm_id, $SEQ_KEY, $id);
//釋放信號量,相當于解鎖
sem_release($sem_id);
//關閉共享內存關聯
shm_detach($shm_id);
echo "序列號ID:{$id}";
?>

009行,定義了一個16進制的整形KEY,在php中只支持System V的IPC機制,需要通過一個KEY關聯到指定的資源(消息隊列、信號量、共享內存)。
010 行,定義了一個在共享內存中存儲遞增ID的KEY,這是php對System V共享內存的閑置:需要通過類似hashtable的KEY-VALUE方式存儲變量。在上面的代碼中使用共享內存做ID的存儲容器,也可以換為 Session、文件等其他機制,本文重點是信號量,有關共享內存的知識以后在講(別忘了前面推薦的那本書)。
013行,獲得系統中的以1234為KEY的信號量,如果系統中沒有就創建一個。
015行,同13行相似,獲得系統中的以1234為KEY的共享內存,如果系統中沒有就創建一個,第二個參數64表示創建64bytes大小的共享內存。
018~034 行,同步代碼區,當一個進程或線程執行sem_acquire函數占有了信號量,到它調用sem_release函數釋放信號量的過程內,其他進程或線程執行到sem_acquire會阻塞。021行從共享內存中獲得ID,函數shm_get_var前綴"@"是為了屏蔽出錯信息(第一次執行時,共享內存中并沒有以"SEQ"為KEY的數據,會在頁面上打印警告信息)。
其他語句非常簡單,不需多講。
程序編好后,訪問這個php頁面,會遞增的輸出數字。
我們可以通過系統命令ipcs查看在程序創建的信號量和共享內存:
$ 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
前兩段分別是共享內存和信號量,0x00001234既是我們創建的KEY。
也可以通過命令ipcrm刪除:
$ ipcrm -M 0x00001234 #刪除共享內存
$ ipcrm -S 0x00001234 #刪除信號量
---------------------------------------------
php手冊中關于IPC的資料非常少,這點也不難想象,Stevens已經在十幾年前講得透透的東東,在php中只是包裝了一下,還有多少必要去深入說明呢?
文本只是借著ID說了說信號量的使用,如果您有更簡單的生成自增ID的辦法,還望賜教。
可能有朋友還想了解信號量的執行效率,我這里用一句過時的流行語總結: 相當的快。

php技術PHP下通過系統信號量加鎖方式獲取遞增序列ID,轉載需保留來源!

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

主站蜘蛛池模板: 91精品在线国产 | 诱受H嗯啊巨肉舍友1V1 | 第一精品福利导福航 | 亚洲国产在线综合018 | 二色AV天堂在线 | 富婆大保健嗷嗷叫普通话对白 | 亚洲免费无l码中文在线视频 | 久久亚洲高清观看 | 少妇的肉体AA片免费 | 午夜男女爽爽羞羞影院在线观看 | 成人毛片18岁女人毛片免费看 | 亚洲AV国产精品无码精 | 青青青视频在线 | 别停好爽好深好大好舒服视频 | 免费果冻传媒在线完整观看 | 王雨纯羞羞 | 九九色精品国偷自产视频 | 狠狠色综合久久婷婷 | 国产精品网红女主播久久久 | 一手揉着乳头一手模仿抽插视频 | 伊人网综合在线观看 | 97免费在线视频 | 日韩一卡二卡三卡四卡免费观在线 | 男女夜晚在爽视频免费观看 | 国产第一页在线视频 | 99久久精品免费看国产一区二区三区 | 狠狠躁日日躁人人爽 | 美女黄图大全 | 亚洲成片在线看 | 波多久久亚洲精品AV无码 | 玄幻全黄h全肉后宫 | 亚洲 欧美 中文 日韩 视频 | 欧美一级做a爰片免费 | 玩高中女同桌肉色短丝袜脚文 | 国产1广场舞丰满老女偷 | 亚洲无吗在线视频 | 毛片基地看看成人免费 | 秋霞伦理高清视频在线 | SM高H黄暴NP辣H调教性奴 | 内射少妇36P亚洲区 内射少妇36P九色 | 91久久偷偷做嫩草影院免费看 |