成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

PHP編程中的鎖

瀏覽:159日期:2022-09-12 13:11:56

最近看了《理解Linux進程》這本開源書,鏈接。該書描述了linux中的進程概念,對鎖和進程間通信(IPC)有一些總結。不過該書的描述語言是golang, 平時用的比較少,就想對應概念找找php中的接口。

文件鎖

全名叫advisory file lock, 書中有提及。 這類鎖比較常見,例如 mysql, php-fpm 啟動之后都會有一個pid文件記錄了進程id,這個文件就是文件鎖。

這個鎖可以防止重復運行一個進程,例如在使用crontab時,限定每一分鐘執行一個任務,但這個進程運行時間可能超過一分鐘,如果不用進程鎖解決沖突的話兩個進程一起執行就會有問題。

使用PID文件鎖還有一個好處,方便進程向自己發停止或者重啟信號。例如重啟php-fpm的命令為

kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`

發送USR2信號給pid文件記錄的進程,信號屬于進程通信,會另開一個篇幅。

php的接口為flock,文檔比較詳細。先看一下定義,bool flock ( resource $handle , int $operation [, int &$wouldblock ] ).

$handle是文件系統指針,是典型地由 fopen() 創建的 resource(資源)。這就意味著使用flock必須打開一個文件。

$operation是操作類型。

&$wouldblock如果鎖是阻塞的,那么這個變量會設為1.

需要注意的是,這個函數默認是阻塞的,如果想非阻塞可以在 operation 加一個 bitmaskLOCK_NB. 接下來測試一下。

$pid_file = '/tmp/process.pid';$pid = posix_getpid();$fp = fopen($pid_file, ’w+’);if(flock($fp, LOCK_EX | LOCK_NB)){ echo 'got the lock n'; ftruncate($fp, 0); // truncate file fwrite($fp, $pid); fflush($fp); // flush output before releasing the lock sleep(300); // long running process flock($fp, LOCK_UN); // 釋放鎖定} else { echo 'Cannot get pid lock. The process is already up n';}fclose($fp);

保存為process.php,運行php process.php &, 此時再次運行php process.php,就可以看到錯誤提示。flock也有共享鎖,LOCK_SH.

互斥鎖和讀寫鎖sync模塊中的Mutex

Mutex是一個組合詞,mutual exclusion。用pecl安裝一下sync模塊,pecl install sync。 文檔中的SyncMutex只有兩個方法,lock 和 unlock, 我們就直接上代碼測試吧。沒有用IDE寫,所以cs異常丑陋,請無視。

$mutex = new SyncMutex('UniqueName');for($i=0; $i<2; $i++){ $pid = pcntl_fork(); if($pid <0){die('fork failed'); }elseif ($pid>0){echo 'parent process n'; }else{echo 'child process {$i} is born. n';obtainLock($mutex, $i); }}while (pcntl_waitpid(0, $status) != -1) { $status = pcntl_wexitstatus($status); echo 'Child $status completedn'; }function obtainLock ($mutex, $i){ echo 'process {$i} is getting the mutex n'; $res = $mutex->lock(200); sleep(1); if (!$res){echo 'process {$i} unable to lock mutex. n'; }else{echo 'process {$i} successfully got the mutex n';$mutex->unlock(); } exit();}

保存為mutex.php, runphp mutex.php, output is

parent process parent process child process 1 is born. process 1 is getting the mutex child process 0 is born. process 0 is getting the mutex process 1 successfully got the mutex Child 0 completedprocess 0 unable to lock mutex. Child 0 completed

這里子進程0和1不一定誰在前面。但是總有一個得不到鎖。這里SyncMutex::lock(int $millisecond)的參數是 millisecond, 代表阻塞的時長, -1 為無限阻塞。

sync模塊中的讀寫鎖

SyncReaderWriter的方法類似,readlock,readunlock,writelock,writeunlock,成對出現即可,沒有寫測試代碼,應該和Mutex的代碼一致,把鎖替換一下就可以。

sync模塊中的Event

感覺和golang中的Cond比較像,wait()阻塞,fire()喚醒Event阻塞的一個進程。有一篇好文介紹了Cond, 可以看出Cond就是鎖的一種固定用法。SyncEvent也一樣。php文檔中的例子顯示,fire()方法貌似可以用在web應用中。

上測試代碼

for($i=0; $i<3; $i++){ $pid = pcntl_fork(); if($pid <0){die('fork failed'); }elseif ($pid>0){//echo 'parent process n'; }else{echo 'child process {$i} is born. n';switch ($i) {case 0: wait(); break;case 1: wait(); break;case 2: sleep(1); fire(); break;} }}while (pcntl_waitpid(0, $status) != -1) { $status = pcntl_wexitstatus($status); echo 'Child $status completedn'; }function wait(){ $event = new SyncEvent('UniqueName'); echo 'before waiting. n'; $event->wait(); echo 'after waiting. n'; exit();}function fire(){ $event = new SyncEvent('UniqueName'); $event->fire(); exit();}

這里故意少寫一個fire(), 所以程序會阻塞,證明了 fire() 一次只喚醒一個進程。

pthreads模塊

貌似也看到了Mutex, Cond, Pool. 沒來得及看,看完再補充。

信號量sync模塊中的信號量

SyncSemaphore文檔中顯示,它和Mutex的不同之處,在于Semaphore一次可以被多個進程(或線程)得到,而Mutex一次只能被一個得到。所以在SyncSemaphore的構造函數中,有一個參數指定信號量可以被多少進程得到。public SyncSemaphore::__construct ([ string $name [, integer $initialval [, bool $autounlock ]]] )就是這個$initialval(initial value)

$lock = new SyncSemaphore('UniqueName', 2);for($i=0; $i<2; $i++){ $pid = pcntl_fork(); if($pid <0){die('fork failed'); }elseif ($pid>0){echo 'parent process n'; }else{echo 'child process {$i} is born. n';obtainLock($lock, $i); }}while (pcntl_waitpid(0, $status) != -1) { $status = pcntl_wexitstatus($status); echo 'Child $status completedn'; }function obtainLock ($lock, $i){ echo 'process {$i} is getting the lock n'; $res = $lock->lock(200); sleep(1); if (!$res){echo 'process {$i} unable to lock lock. n'; }else{echo 'process {$i} successfully got the lock n';$lock->unlock(); } exit();}

這時候兩個進程都能得到鎖。

sysvsem模塊中的信號量

sem_get創建信號量

sem_remove刪除信號量(一般不用)

sem_acquire請求得到信號量

sem_release釋放信號量。和sem_acquire成對使用。

$key = ftok(’/tmp’, ’c’);$sem = sem_get($key);for($i=0; $i<2; $i++){ $pid = pcntl_fork(); if($pid <0){die('fork failed'); }elseif ($pid>0){//echo 'parent process n'; }else{echo 'child process {$i} is born. n';obtainLock($sem, $i); }}while (pcntl_waitpid(0, $status) != -1) { $status = pcntl_wexitstatus($status); echo 'Child $status completedn'; }sem_remove($sem); // finally remove the semfunction obtainLock ($sem, $i){ echo 'process {$i} is getting the sem n'; $res = sem_acquire($sem, true); sleep(1); if (!$res){echo 'process {$i} unable to get sem. n'; }else{echo 'process {$i} successfully got the sem n';sem_release($sem); } exit();}

這里有一個問題,sem_acquire()第二個參數$nowait默認為false,阻塞。我設為了true,如果得到鎖失敗,那么后面的sem_release會報警告PHP Warning: sem_release(): SysV semaphore 4 (key 0x63000081) is not currently acquired in /home/jason/sysvsem.php on line 33, 所以這里的release操作必須放在得到鎖的情況下執行,前面的幾個例子中沒有這個問題,沒得到鎖執行release也不會報錯。當然最好還是成對出現,確保得到鎖的情況下再release。

此外,ftok這個方法的參數有必要說明下,第一個 必須是existing, accessable的文件, 一般使用項目中的文件,第二個是單字符字符串。返回一個int。

輸出為

parent process parent process child process 1 is born. process 1 is getting the mutex child process 0 is born. process 0 is getting the mutex process 1 successfully got the mutex Child 0 completedprocess 0 unable to lock mutex. Child 0 completed

最后,如果文中有錯誤的地方,希望大神指出,幫助一下菜鳥進步,謝謝各位。

標簽: PHP
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
国产清纯在线一区二区www| 亚洲国产成人精品视频| 日韩欧美资源站| 欧日韩精品视频| 鲁大师成人一区二区三区| 亚洲精品系列| 妖精视频成人观看www| 日韩午夜黄色| 国产偷久久久精品专区| 国产精品视频久久一区| 久久天天狠狠| 欧美三级中文字幕| 欧美一级艳片视频免费观看| 欧美日韩在线一区二区| 日韩视频免费观看高清完整版在线观看 | 91丨porny丨中文| 91在线porny国产在线看| 欧美日韩亚洲免费| 亚洲国产日本| 久久久久久久波多野高潮日日| 欧美亚洲色图校园春色| 色伊人久久综合中文字幕| 欧洲生活片亚洲生活在线观看| 欧美又粗又大又爽| 91超碰这里只有精品国产| 日韩免费成人网| 中文字幕不卡在线| 亚洲成人黄色影院| 国精产品一区一区三区mba桃花 | 亚洲一区二区三区四区在线观看 | 欧美色国产精品| 欧美福利视频一区| 国产欧美日韩一区二区三区在线观看 | 中文在线免费一区三区高中清不卡| 国产精品视频看| 午夜国产不卡在线观看视频| 国内外成人在线视频| 91丨porny丨户外露出| 亚洲精品久久| 欧美日韩一区二区三区四区| 久久免费美女视频| 一区二区三区中文字幕精品精品 | 老司机午夜精品| 91亚洲午夜精品久久久久久| 国产一区二区三区的电影| 欧美日韩国产免费| 国产精品电影一区二区| 久久精品国产一区二区三| 91在线一区二区| 另类图片国产| 久久看人人爽人人| 午夜精品久久久| 99v久久综合狠狠综合久久| 国产精品一区视频| 精品动漫一区二区三区在线观看| 一区二区在线免费| 成人免费高清在线| 亚洲女同同性videoxma| 欧美精品一区二区三区一线天视频| 亚洲精品午夜久久久| 国产aⅴ精品一区二区三区色成熟| 亚洲美女黄色| 日韩精品中文字幕一区 | 亚洲精品在线视频观看| 日韩视频一区二区三区在线播放| 亚洲一区二区视频在线| 不卡的av在线| 欧美最猛黑人xxxxx猛交| 中文字幕在线观看一区二区| 国产91精品精华液一区二区三区| 亚洲影音一区| 亚洲国产高清在线观看视频| 国产精品 日产精品 欧美精品| 亚洲一区免费| 国产精品福利在线播放| 成人av影视在线观看| 在线亚洲人成电影网站色www| 亚洲色图自拍偷拍美腿丝袜制服诱惑麻豆 | 国产午夜精品一区二区| 激情丁香综合五月| 久久久久高清| 亚洲少妇中出一区| 欧美系列一区| 久久久午夜精品理论片中文字幕| 久久国产精品72免费观看| 国产精品入口66mio| 亚洲视频在线一区| 国产精品porn| 亚洲国产成人自拍| 99久久国产综合精品色伊| 4438x成人网最大色成网站| 日韩电影在线免费观看| 亚洲深夜福利| 亚洲精品亚洲人成人网 | 日韩一级视频免费观看在线| 老司机精品视频线观看86| 色先锋aa成人| 天堂va蜜桃一区二区三区 | 26uuu国产一区二区三区| 成人一区二区三区在线观看| 91精品国产综合久久久久久久久久 | 麻豆精品网站| 性做久久久久久久免费看| 中文精品一区二区三区| 亚洲黄网站在线观看| 国产精品美女| 午夜视频一区二区三区| 久久亚洲国产精品日日av夜夜| 亚洲第四色夜色| 色偷偷久久人人79超碰人人澡| 首页国产丝袜综合| 欧美色国产精品| 国产91精品露脸国语对白| 日韩一级大片在线| 91女人视频在线观看| 欧美激情在线一区二区三区| 亚洲小说欧美另类社区| 夜夜嗨av一区二区三区四季av| 国产视频欧美| 裸体歌舞表演一区二区| 91精品国产免费| 91丨porny丨首页| 亚洲人成精品久久久久| 亚洲一区区二区| 激情文学综合丁香| www欧美成人18+| 黄色免费成人| 日韩电影一区二区三区四区| 欧美日韩精品免费| 97成人超碰视| 亚洲欧美日韩一区| 欧美色图激情小说| 99麻豆久久久国产精品免费| 国产精品成人免费在线| 日本韩国欧美一区| 成人午夜免费av| 亚洲日本中文字幕区| 色狠狠色噜噜噜综合网| 成人福利视频网站| 亚洲精品日韩一| 欧美性受极品xxxx喷水| 91在线视频观看| 一区二区激情视频| 91麻豆精品国产自产在线观看一区| 91在线免费播放| 亚洲国产日韩精品| 日韩精品中午字幕| 亚洲影视综合| 成人免费福利片| 亚洲电影一级黄| 精品国产乱码久久久久久图片| 亚洲激情欧美| 国产不卡视频在线观看| 亚洲另类在线一区| 日韩一区和二区| 国产精品久久国产愉拍| 高清shemale亚洲人妖| 一区二区成人在线| 欧美精品一区二区高清在线观看| 午夜亚洲影视| 99热99精品| 蜜臀国产一区二区三区在线播放| 国产精品欧美综合在线| 91.xcao| 西西裸体人体做爰大胆久久久| jizzjizzjizz欧美| 免费在线看一区| 亚洲视频你懂的| 337p粉嫩大胆色噜噜噜噜亚洲| 91精品办公室少妇高潮对白| 国产在线精品二区| 顶级嫩模精品视频在线看| 午夜精品一区二区三区免费视频 | 亚洲第一精品在线| 综合久久给合久久狠狠狠97色| 欧美精品v国产精品v日韩精品| 免费日韩av片| 午夜精品区一区二区三| 国产黄人亚洲片| 美女国产一区二区三区| 樱花影视一区二区| 国产精品乱码久久久久久| 日韩一区二区三区免费看 | 国产色产综合产在线视频| 91麻豆精品国产91久久久久久久久 | 91黄色激情网站| 国产伦精品一区二区三区四区免费 | 日本不卡不码高清免费观看| 亚洲色图.com| 国产精品无圣光一区二区| 欧美成人欧美edvon| 欧美老年两性高潮| 在线视频国内自拍亚洲视频| 亚洲一区激情| 国产精品乱码| 国产日产高清欧美一区二区三区| 亚洲无线一线二线三线区别av| 色综合天天性综合| 91丨九色丨黑人外教| www..com久久爱|