欧美成人午夜免费全部完,亚洲午夜福利精品久久,а√最新版在线天堂,另类亚洲综合区图片小说区,亚洲欧美日韩精品色xxx

扣丁學(xué)堂剖析關(guān)于PHP視頻教程之文件鎖 互斥鎖 讀寫(xiě)鎖詳解

2017-12-29 10:20:53 1352瀏覽

        今天扣丁學(xué)堂給大家主要介紹了PHP開(kāi)發(fā)程序中的文件鎖、互斥鎖、讀寫(xiě)鎖使用技巧解析,其中重點(diǎn)講解了sync模塊和pthreads模塊中的使用實(shí)例,需要的朋友可以參考下,下面我們一起來(lái)看一下吧。


扣丁學(xué)堂剖析關(guān)于PHP視頻教程之文件鎖 互斥鎖 讀寫(xiě)鎖詳解



文件鎖

全名叫advisoryfilelock,書(shū)中有提及。這類(lèi)鎖比較常見(jiàn),例如mysql,php-fpm啟動(dòng)之后都會(huì)有一個(gè)pid文件記錄了進(jìn)程id,這個(gè)文件就是文件鎖。

這個(gè)鎖可以防止重復(fù)運(yùn)行一個(gè)進(jìn)程,例如在使用crontab時(shí),限定每一分鐘執(zhí)行一個(gè)任務(wù),但這個(gè)進(jìn)程運(yùn)行時(shí)間可能超過(guò)一分鐘,如果不用進(jìn)程鎖解決沖突的話兩個(gè)進(jìn)程一起執(zhí)行就會(huì)有問(wèn)題。

使用PID文件鎖還有一個(gè)好處,方便進(jìn)程向自己發(fā)停止或者重啟信號(hào)。例如重啟php-fpm的命令為

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

發(fā)送USR2信號(hào)給pid文件記錄的進(jìn)程,信號(hào)屬于進(jìn)程通信,會(huì)另開(kāi)一個(gè)篇幅。

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

$handle是文件系統(tǒng)指針,是典型地由fopen()創(chuàng)建的resource(資源)。這就意味著使用flock必須打開(kāi)一個(gè)文件。

$operation是操作類(lèi)型。

&$wouldblock如果鎖是阻塞的,那么這個(gè)變量會(huì)設(shè)為1.

需要注意的是,這個(gè)函數(shù)默認(rèn)是阻塞的,如果想非阻塞可以在operation加一個(gè)bitmaskLOCK_NB.接下來(lái)測(cè)試一下。

$pid_file="/tmp/process.pid";

$pid=posix_getpid();

$fp=fopen($pid_file,'w+');

if(flock($fp,LOCK_EX|LOCK_NB)){

echo"gotthelock\n";

ftruncate($fp,0);//truncatefile

fwrite($fp,$pid);

fflush($fp);//flushoutputbeforereleasingthelock

sleep(300);//longrunningprocess

flock($fp,LOCK_UN);//釋放鎖定

}else{

echo"Cannotgetpidlock.Theprocessisalreadyup\n";

}

fclose($fp);

保存為process.php,運(yùn)行phpprocess.php&,此時(shí)再次運(yùn)行phpprocess.php,就可以看到錯(cuò)誤提示。flock也有共享鎖,LOCK_SH.

互斥鎖和讀寫(xiě)鎖

sync模塊中的Mutex:

Mutex是一個(gè)組合詞,mutualexclusion。用pecl安裝一下sync模塊,peclinstallsync。文檔中的SyncMutex只有兩個(gè)方法,lock和unlock,我們就直接上代碼測(cè)試吧。沒(méi)有用IDE寫(xiě),所以cs異常丑陋,請(qǐng)無(wú)視。

$mutex=newSyncMutex("UniqueName");

for($i=0;$i<2;$i++){

$pid=pcntl_fork();

if($pid<0){

die("forkfailed");

}elseif($pid>0){

echo"parentprocess\n";

}else{

echo"childprocess{$i}isborn.\n";

obtainLock($mutex,$i);

}

}

while(pcntl_waitpid(0,$status)!=-1){

$status=pcntl_wexitstatus($status);

echo"Child$statuscompleted\n";

}

functionobtainLock($mutex,$i){

echo"process{$i}isgettingthemutex\n";

$res=$mutex->lock(200);

sleep(1);

if(!$res){

echo"process{$i}unabletolockmutex.\n";

}else{

echo"process{$i}successfullygotthemutex\n";

$mutex->unlock();

}

exit();

}

保存為mutex.php,runphpmutex.php,outputis

parentprocess

parentprocess

childprocess1isborn.

process1isgettingthemutex

childprocess0isborn.

process0isgettingthemutex

process1successfullygotthemutex

Child0completed

process0unabletolockmutex.

Child0completed

這里子進(jìn)程0和1不一定誰(shuí)在前面。但是總有一個(gè)得不到鎖。這里SyncMutex::lock(int$millisecond)的參數(shù)是millisecond,代表阻塞的時(shí)長(zhǎng),-1為無(wú)限阻塞。

sync模塊中的讀寫(xiě)鎖:

SyncReaderWriter的方法類(lèi)似,readlock,readunlock,writelock,writeunlock,成對(duì)出現(xiàn)即可,沒(méi)有寫(xiě)測(cè)試代碼,應(yīng)該和Mutex的代碼一致,把鎖替換一下就可以。

sync模塊中的Event:

感覺(jué)和golang中的Cond比較像,wait()阻塞,fire()喚醒Event阻塞的一個(gè)進(jìn)程。有一篇好文介紹了Cond,可以看出Cond就是鎖的一種固定用法。SyncEvent也一樣。

php文檔中的例子顯示,fire()方法貌似可以用在web應(yīng)用中。

上測(cè)試代碼

for($i=0;$i<3;$i++){

$pid=pcntl_fork();

if($pid<0){

die("forkfailed");

}elseif($pid>0){

//echo"parentprocess\n";

}else{

echo"childprocess{$i}isborn.\n";

switch($i){

case0:

wait();

break;

case1:

wait();

break;

case2:

sleep(1);

fire();

break;

}

}

}

while(pcntl_waitpid(0,$status)!=-1){

$status=pcntl_wexitstatus($status);

echo"Child$statuscompleted\n";

}

functionwait(){

$event=newSyncEvent("UniqueName");

echo"beforewaiting.\n";

$event->wait();

echo"afterwaiting.\n";

exit();

}

functionfire(){

$event=newSyncEvent("UniqueName");

$event->fire();

exit();

}

這里故意少寫(xiě)一個(gè)fire(),所以程序會(huì)阻塞,證明了fire()一次只喚醒一個(gè)進(jìn)程。

pthreads模塊

鎖定和解鎖互斥量:

函數(shù):

pthread_mutex_lock(mutex)

pthread_mutex_trylock(mutex)

pthread_mutex_unlock(mutex)

用法:

線程用pthread_mutex_lock()函數(shù)去鎖定指定的mutex變量,若該mutex已經(jīng)被另外一個(gè)線程鎖定了,該調(diào)用將會(huì)阻塞線程直到mutex被解鎖。

pthread_mutex_trylock()willattempttolockamutex.However,ifthemutexisalreadylocked,theroutinewillreturnimmediatelywitha"busy"errorcode.Thisroutinemaybeusefulinpthread_mutex_trylock().

嘗試著去鎖定一個(gè)互斥量,然而,若互斥量已被鎖定,程序會(huì)立刻返回并返回一個(gè)忙錯(cuò)誤值。該函數(shù)在優(yōu)先級(jí)改變情況下阻止死鎖是非常有用的。線程可以用pthread_mutex_unlock()解鎖自己占用的互斥量。在一個(gè)線程完成對(duì)保護(hù)數(shù)據(jù)的使用,而其它線程要獲得互斥量在保護(hù)數(shù)據(jù)上工作時(shí),可以調(diào)用該函數(shù)。若有一下情形則會(huì)發(fā)生錯(cuò)誤:

互斥量已經(jīng)被解鎖

互斥量被另一個(gè)線程占用

互斥量并沒(méi)有多么“神奇”的,實(shí)際上,它們就是參與的線程的“君子約定”。寫(xiě)代碼時(shí)要確信正確地鎖定,解鎖互斥量。

Q:有多個(gè)線程等待同一個(gè)鎖定的互斥量,當(dāng)互斥量被解鎖后,那個(gè)線程會(huì)第一個(gè)鎖定互斥量?

A:除非線程使用了優(yōu)先級(jí)調(diào)度機(jī)制,否則,線程會(huì)被系統(tǒng)調(diào)度器去分配,那個(gè)線程會(huì)第一個(gè)鎖定互斥量是隨機(jī)的。

#include

#include

#include

#include

typedefstructct_sum

{

intsum;

pthread_mutex_tlock;

}ct_sum;

void*add1(void*cnt)

{

pthread_mutex_lock(&(((ct_sum*)cnt)->lock));

for(inti=0;i<50;i++)

{

(*(ct_sum*)cnt).sum+=i;

}

pthread_mutex_unlock(&(((ct_sum*)cnt)->lock));

pthread_exit(NULL);

return0;

}

void*add2(void*cnt)

{

pthread_mutex_lock(&(((ct_sum*)cnt)->lock));

for(inti=50;i<101;i++)

{

(*(ct_sum*)cnt).sum+=i;

}

pthread_mutex_unlock(&(((ct_sum*)cnt)->lock));

pthread_exit(NULL);

return0;

}

intmain(void)

{

pthread_tptid1,ptid2;

ct_sumcnt;

pthread_mutex_init(&(cnt.lock),NULL);

cnt.sum=0;

pthread_create(&ptid1,NULL,add1,&cnt);

pthread_create(&ptid2,NULL,add2,&cnt);

pthread_join(ptid1,NULL);

pthread_join(ptid2,NULL);

printf("sum%d\n",cnt.sum);

pthread_mutex_destroy(&(cnt.lock));

return0;

}

信號(hào)量

sync模塊中的信號(hào)量:

SyncSemaphore文檔中顯示,它和Mutex的不同之處,在于Semaphore一次可以被多個(gè)進(jìn)程(或線程)得到,而Mutex一次只能被一個(gè)得到。所以在SyncSemaphore的構(gòu)造函數(shù)中,有一個(gè)參數(shù)指定信號(hào)量可以被多少進(jìn)程得到。

publicSyncSemaphore::__construct([string$name[,integer$initialval[,bool$autounlock]]])就是這個(gè)$initialval(initialvalue)

$lock=newSyncSemaphore("UniqueName",2);

for($i=0;$i<2;$i++){

$pid=pcntl_fork();

if($pid<0){

die("forkfailed");

}elseif($pid>0){

echo"parentprocess\n";

}else{

echo"childprocess{$i}isborn.\n";

obtainLock($lock,$i);

}

}

while(pcntl_waitpid(0,$status)!=-1){

$status=pcntl_wexitstatus($status);

echo"Child$statuscompleted\n";

}

functionobtainLock($lock,$i){

echo"process{$i}isgettingthelock\n";

$res=$lock->lock(200);

sleep(1);

if(!$res){

echo"process{$i}unabletolocklock.\n";

}else{

echo"process{$i}successfullygotthelock\n";

$lock->unlock();

}

exit();

}

這時(shí)候兩個(gè)進(jìn)程都能得到鎖。

sysvsem模塊中的信號(hào)量

sem_get創(chuàng)建信號(hào)量

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

sem_acquire請(qǐng)求得到信號(hào)量

sem_release釋放信號(hào)量。和sem_acquire成對(duì)使用。

$key=ftok('/tmp','c');

$sem=sem_get($key);

for($i=0;$i<2;$i++){

$pid=pcntl_fork();

if($pid<0){

die("forkfailed");

}elseif($pid>0){

//echo"parentprocess\n";

}else{

echo"childprocess{$i}isborn.\n";

obtainLock($sem,$i);

}

}

while(pcntl_waitpid(0,$status)!=-1){

$status=pcntl_wexitstatus($status);

echo"Child$statuscompleted\n";

}

sem_remove($sem);//finallyremovethesem

functionobtainLock($sem,$i){

echo"process{$i}isgettingthesem\n";

$res=sem_acquire($sem,true);

sleep(1);

if(!$res){

echo"process{$i}unabletogetsem.\n";

}else{

echo"process{$i}successfullygotthesem\n";

sem_release($sem);

}

exit();

}

這里有一個(gè)問(wèn)題,sem_acquire()第二個(gè)參數(shù)$nowait默認(rèn)為false,阻塞。我設(shè)為了true,如果得到鎖失敗,那么后面的sem_release會(huì)報(bào)警告PHPWarning:sem_release():SysVsemaphore4(key0x63000081)isnotcurrentlyacquiredin/home/jason/sysvsem.phponline33,所以這里的release操作必須放在得到鎖的情況下執(zhí)行,前面的幾個(gè)例子中沒(méi)有這個(gè)問(wèn)題,沒(méi)得到鎖執(zhí)行release也不會(huì)報(bào)錯(cuò)。當(dāng)然最好還是成對(duì)出現(xiàn),確保得到鎖的情況下再release。

此外,ftok這個(gè)方法的參數(shù)有必要說(shuō)明下,第一個(gè)必須是existing,accessable的文件,一般使用項(xiàng)目中的文件,第二個(gè)是單字符字符串。返回一個(gè)int。

輸出為

parentprocess

parentprocess

childprocess1isborn.

process1isgettingthemutex

childprocess0isborn.

process0isgettingthemutex

process1successfullygotthemutex

Child0completed

process0unabletolockmutex.

Child0completed

        以上就是扣丁學(xué)堂PHP視頻教程中關(guān)于文件鎖、互斥鎖、讀寫(xiě)鎖的詳解,最后想要學(xué)習(xí)PHP開(kāi)發(fā)技術(shù)的小伙伴不要猶豫了,扣丁學(xué)堂是PHP培訓(xùn)技術(shù)的最佳選擇,想要PHP視頻教程的小伙伴現(xiàn)在就聯(lián)系我們的咨詢(xún)老師領(lǐng)取吧,機(jī)會(huì)總是留給有準(zhǔn)備的人的!扣丁學(xué)堂PHP開(kāi)發(fā)工程師技術(shù)交流群:374332265。


扣丁學(xué)堂微信公眾號(hào)



關(guān)注微信公眾號(hào)獲取更多的學(xué)習(xí)資料



查看更多關(guān)于“php培訓(xùn)資訊的相關(guān)文章>>

標(biāo)簽: PHP培訓(xùn) PHP視頻教程 PHP從入門(mén)到精通 PHP學(xué)習(xí)路線圖 PHP開(kāi)發(fā)工程師

熱門(mén)專(zhuān)區(qū)

暫無(wú)熱門(mén)資訊

課程推薦

微信
微博
15311698296

全國(guó)免費(fèi)咨詢(xún)熱線

郵箱:codingke@1000phone.com

官方群:148715490

北京千鋒互聯(lián)科技有限公司版權(quán)所有   北京市海淀區(qū)寶盛北里西區(qū)28號(hào)中關(guān)村智誠(chéng)科創(chuàng)大廈4層
京ICP備2021002079號(hào)-2   Copyright ? 2017 - 2022
返回頂部 返回頂部