站長(zhǎng)資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

簡(jiǎn)單了解php進(jìn)程通信之信號(hào)量

本篇文章給大家?guī)?lái)了關(guān)于PHP的相關(guān)知識(shí),信號(hào)量又稱(chēng)為信號(hào)燈、旗語(yǔ) 用來(lái)解決進(jìn)程(線程同步的問(wèn)題),類(lèi)似于一把鎖,訪問(wèn)前獲取鎖(獲取不到則等待),訪問(wèn)后釋放鎖,文中通過(guò)示例代碼介紹的非常詳細(xì),希望對(duì)大家有幫助。

簡(jiǎn)單了解php進(jìn)程通信之信號(hào)量

(推薦教程:PHP視頻教程)

常見(jiàn)進(jìn)程通信方式

簡(jiǎn)單了解php進(jìn)程通信之信號(hào)量

一些理論基礎(chǔ)

  • 臨界資源:每次僅允許一個(gè)進(jìn)程訪問(wèn)的資源。
  • 臨界區(qū):每個(gè)進(jìn)程中訪問(wèn)臨界資源的那段代碼叫臨界區(qū)

所謂臨界區(qū)(也稱(chēng)為臨界段)就是訪問(wèn)和操作共享數(shù)據(jù)的代碼段。

進(jìn)程互斥:兩個(gè)或以上的進(jìn)程不能同時(shí)進(jìn)入關(guān)于同一組共享變量的臨界區(qū)域,即一個(gè)進(jìn)程正在訪問(wèn)臨界資源,另一個(gè)進(jìn)程要想訪問(wèn)必須等待。

進(jìn)程同步:主要研究如何確定數(shù)個(gè)進(jìn)程之間的執(zhí)行順序和避免數(shù)據(jù)競(jìng)爭(zhēng)的問(wèn)題 即,如何讓多個(gè)進(jìn)程能一塊很好的協(xié)作運(yùn)行

所謂同步,就是并發(fā)進(jìn)程/線程在一些關(guān)鍵點(diǎn)上可能需要互相等待與互通消息,這種相互制約的等待與互通信息稱(chēng)為進(jìn)程/線程同步。

舉個(gè)生活的同步例子,你肚子餓了想要吃飯,你叫媽媽早點(diǎn)做菜,媽媽聽(tīng)到后就開(kāi)始做菜,但是在媽媽沒(méi)有做完飯之前,你必須阻塞等待,等媽媽做完飯后,自然會(huì)通知你,接著你吃飯的事情就可以進(jìn)行了。

注意,同步與互斥是兩種不同的概念:

同步就好比:「操作 A 應(yīng)在操作 B 之前執(zhí)行」,「操作 C 必須在操作 A 和操作 B 都完成之后才能執(zhí)行」等;

互斥就好比:「操作 A 和操作 B 不能在同一時(shí)刻執(zhí)行」;

system V 信號(hào)量

信號(hào)量用途:主要用于多進(jìn)程或多線程對(duì)公共資源對(duì)象的訪問(wèn)控制。 用來(lái)解決多進(jìn)程(多線程同步的問(wèn)題),類(lèi)似于一把鎖,訪問(wèn)前獲取鎖(獲取不到則等待),訪問(wèn)后釋放鎖。

多進(jìn)程/多線程一般是并發(fā)執(zhí)行,如果對(duì)公共資源訪問(wèn)沒(méi)有做同步處理,很容易造成數(shù)據(jù)破壞

信號(hào)量其實(shí)是一個(gè)整型的計(jì)數(shù)器,主要用于實(shí)現(xiàn)進(jìn)程間的互斥與同步,而不是用于緩存進(jìn)程間通信的數(shù)據(jù)。

信號(hào)量表示資源的數(shù)量,控制信號(hào)量的方式有兩種原子操作:

一個(gè)是 P 操作,這個(gè)操作會(huì)把信號(hào)量減去 -1,相減后如果信號(hào)量 < 0,則表明資源已被占用,進(jìn)程需阻塞等待;相減后如果信號(hào)量 >= 0,則表明還有資源可使用,進(jìn)程可正常繼續(xù)執(zhí)行。

另一個(gè)是 V 操作,這個(gè)操作會(huì)把信號(hào)量加上 1,相加后如果信號(hào)量 <= 0,則表明當(dāng)前有阻塞中的進(jìn)程,于是會(huì)將該進(jìn)程喚醒運(yùn)行;相加后如果信號(hào)量 > 0,則表明當(dāng)前沒(méi)有阻塞中的進(jìn)程;

P 操作是用在進(jìn)入共享資源之前,V 操作是用在離開(kāi)共享資源之后,這兩個(gè)操作是必須成對(duì)出現(xiàn)的。

舉個(gè)類(lèi)比,2 個(gè)資源的信號(hào)量,相當(dāng)于 2 條火車(chē)軌道,PV 操作如下圖過(guò)程:

簡(jiǎn)單了解php進(jìn)程通信之信號(hào)量

一輛火車(chē)進(jìn)入軌道,相當(dāng)于信號(hào)量的P操作,資源-1,這樣就剩下一條軌道

簡(jiǎn)單了解php進(jìn)程通信之信號(hào)量

接著又一輛火車(chē)占用另一條軌道,也就是P操作,資源-1

簡(jiǎn)單了解php進(jìn)程通信之信號(hào)量

此時(shí)交通信號(hào)燈變?yōu)榧t色,因?yàn)闆](méi)有軌道可用,第三輛火車(chē)必須等待

簡(jiǎn)單了解php進(jìn)程通信之信號(hào)量

第一輛火車(chē)離開(kāi)軌道,相當(dāng)于V操作,此時(shí)軌道資源為1,交通燈變?yōu)榫G燈

簡(jiǎn)單了解php進(jìn)程通信之信號(hào)量

第三輛火車(chē)發(fā)現(xiàn)交通信號(hào)燈變綠,于是進(jìn)入火車(chē)軌道,軌道資源耗盡為0,于是交通信號(hào)燈變?yōu)榧t燈

簡(jiǎn)單了解php進(jìn)程通信之信號(hào)量

在這個(gè)火車(chē)軌道系統(tǒng)中,軌道是公共資源,每輛火車(chē)好比一個(gè)線程,交通信號(hào)燈起的就是信號(hào)量的作用。信號(hào)量可以實(shí)現(xiàn)鎖的互斥操作,也可以實(shí)現(xiàn)進(jìn)程/線程同步

信號(hào)量類(lèi)型

1)二進(jìn)制信號(hào)量(也叫二值信號(hào)量)

此時(shí)信號(hào)量的初值只能是0和1。(二進(jìn)制信號(hào)量可以實(shí)現(xiàn)互斥鎖操作)

2)一般/計(jì)數(shù)信號(hào)量

此時(shí)信號(hào)量的初值可以是任意非負(fù)數(shù)。顯然,其包含二進(jìn)制信號(hào)量。上面舉的火車(chē)軌道例子就可以使用計(jì)數(shù)信號(hào)量來(lái)實(shí)現(xiàn),一般計(jì)數(shù)信號(hào)量與鎖的區(qū)別是它可以允許多個(gè)線程/進(jìn)程(線程的數(shù)量由計(jì)數(shù)信號(hào)量初值定義) 同時(shí)操作公共資源

一般只有在開(kāi)發(fā)多進(jìn)程的時(shí)候才可能遇到需要使用信號(hào)量的場(chǎng)景,phper 幾乎很少有使用信號(hào)量的場(chǎng)景,就算有多進(jìn)程對(duì)公共資源操作,大多也是使用 flock 文件鎖做互斥操作

php模擬多進(jìn)程操作公共資源

<?php $file = "num.txt";//定一個(gè)空文件 $count =0; file_put_contents($file,$count);  $pid = pcntl_fork();//fork 一個(gè)進(jìn)程  if($pid == 0){//子進(jìn)程執(zhí)行邏輯     $x = (int)file_get_contents($file);//讀取文件內(nèi)容     //i 循環(huán)累加     for($i=0; $i<1000; $i++){         $x = $x + 1;     }     //寫(xiě)入文件     file_put_contents($file,$x);     //子進(jìn)程退出     exit(0); } //父進(jìn)程執(zhí)行邏輯 $x = (int)file_get_contents($file); for($i=0; $i<1000; $i++){     $x = $x+1; } //累加寫(xiě)入 file_put_contents($file,$x);

在編寫(xiě)一個(gè)shell 腳本輔助

#!/bin/bash for a in {1..1000} do     (php demo1.php)     b=`cat num.txt`     if [ $b != 2000 ]     then         echo -e "錯(cuò)誤$b"     fi done

按理來(lái)說(shuō),變量 $x 最后寫(xiě)入文件的值應(yīng)該是2000,但很不幸,并不是如此,我們對(duì)上面的腳本執(zhí)行一下:

簡(jiǎn)單了解php進(jìn)程通信之信號(hào)量

運(yùn)行了1000次,發(fā)現(xiàn)出現(xiàn)了變量$x值結(jié)果是 1000 的有8次,雖然發(fā)生錯(cuò)誤的概率比較小,但是在計(jì)算機(jī)里是不能容忍的。

為什么會(huì)出現(xiàn)這種情況,我們知道單核cpu系統(tǒng)里為了實(shí)現(xiàn)多個(gè)程序同時(shí)運(yùn)行的假象,操作系統(tǒng)通常都采用時(shí)間片調(diào)度,一個(gè)進(jìn)程時(shí)間片用完就切換下一個(gè)進(jìn)程運(yùn)行,加上我們的高級(jí)語(yǔ)言不是每一行代碼都是原子性的,比如x = (int)file_get_contents($file) 這行代碼對(duì)于我們來(lái)說(shuō)是不可分割是原子性的,但是經(jīng)過(guò)編譯器編譯成匯編碼【機(jī)器指令】可能是多條指令實(shí)現(xiàn),這樣就會(huì)出現(xiàn)問(wèn)題,如果指令只執(zhí)行到一半進(jìn)程分配的時(shí)間片用完或者被其他進(jìn)程打斷,都有可能造成數(shù)據(jù)損壞,導(dǎo)致最后計(jì)算結(jié)果出現(xiàn)誤差

使用php封裝system v 信號(hào)量集函數(shù)

<?php $file = "num.txt";//定一個(gè)空文件 $count =0; $key = ftok("demo1.php","x"); $sem_id = sem_get($key,1);// 第二個(gè)參數(shù)是個(gè)整數(shù),表示設(shè)置信號(hào)量集,設(shè)置為1 把它當(dāng)做二值信號(hào)量來(lái)用,用于互斥 file_put_contents($file,$count); $pid = pcntl_fork();//fork 一個(gè)進(jìn)程 if($pid == 0){//子進(jìn)程執(zhí)行邏輯 sem_acquire($sem_id); // P -1 操作 獲取一個(gè)信號(hào)量 , 如果為0表示資源被占用進(jìn)程掛起等待信號(hào)量釋放     $x = (int)file_get_contents($file);//讀取文件內(nèi)容     //i 循環(huán)累加     for($i=0; $i<1000; $i++){         $x = $x + 1;     }     //寫(xiě)入文件     file_put_contents($file,$x);        sem_release($sem_id); //V +1 操作 釋放信號(hào)量     //子進(jìn)程退出     exit(0); } //父進(jìn)程執(zhí)行邏輯 sem_acquire($sem_id); // P -1 操作  獲取信號(hào)量, 如果為0表示資源被占用進(jìn)程掛起等待信號(hào)量釋放 $x = (int)file_get_contents($file); for($i=0; $i<1000; $i++){     $x = $x+1; } //累加寫(xiě)入 file_put_contents($file,$x); sem_release($sem_id); //V +1 操作 釋放信號(hào)量

加入信號(hào)量后,那就一定保證100%是2000,絕對(duì)不會(huì)出現(xiàn)其他數(shù)值。

(推薦教程:PHP視頻教程)

贊(0)
分享到: 更多 (0)
網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
亚洲精品无码专区在线播放| 日韩午夜免费视频| 99re热这里只有精品| 人妻少妇无码精品视频区| 日本精品自产拍在线观看中文| 国内精品视频一区二区三区八戒| 日韩精品久久久久久免费| 亚洲精品无码久久久久sm| 精品国产91久久久久久久a | 柠檬福利精品视频导航| 成人日韩熟女高清视频一区 | 热re久久精品国产99热| 国内精品-bt天堂| 99re在线精品视频| 亚洲国产精品久久66| 国产成人精品一区二区秒拍| 久久五月精品中文字幕| 国产高清在线精品一区小说| 日韩一区二区三区在线| 国产成人一区二区三区精品久久| 成人国产精品一区二区网站公司| 最新在线精品国自产拍网站| 精品亚洲成a人片在线观看| 亚洲国产精品一区| 久久99国产精品成人| 日本精品高清一区二区| 中文字幕精品在线观看| 亚洲精品A在线观看| 精品无码一区二区三区水蜜桃| 国产成人精品福利色多多| 精品国产三级a∨在线观看| 最新国产成人亚洲精品影院| 亚洲国语精品自产拍在线观看| 国产99视频精品免视看9| 九九精品在线视频| mm1313亚洲精品国产| 日韩精品电影一区亚洲| 国产剧情AV麻豆香蕉精品| 国产69精品麻豆久久久久| 欧美精品大香伊蕉在人线| 国产成人精品午夜二三区波多野|