php 進階程式設計之多線程
中國廣東省深圳市龍華新區民治街道溪山美地
518131
+86 13113668890
+86 755 29812080
版權聲明
轉載請與作者聯系,轉載時請務必标明文章原始出處和作者資訊及本聲明。

文檔出處:
<a href="http://netkiller.github.io/" target="_top">http://netkiller.github.io</a>
<a href="http://netkiller.sourceforge.net/" target="_top">http://netkiller.sourceforge.net</a>
$date$
摘要
2014-03-12 第一版
2014-05-15 第二版
2014-06-13 第三版
2014-07-24 第四版
我的系列文檔
<a href="http://netkiller.github.io/architect/index.html" target="_top">netkiller architect 手劄</a>
<a href="http://netkiller.github.io/developer/index.html" target="_top">netkiller developer 手劄</a>
<a href="http://netkiller.github.io/php/index.html" target="_top">netkiller php 手劄</a>
<a href="http://netkiller.github.io/python/index.html" target="_top">netkiller python 手劄</a>
<a href="http://netkiller.github.io/testing/index.html" target="_top">netkiller testing 手劄</a>
<a href="http://netkiller.github.io/cryptography/index.html" target="_top">netkiller cryptography 手劄</a>
<a href="http://netkiller.github.io/linux/index.html" target="_top">netkiller linux 手劄</a>
<a href="http://netkiller.github.io/debian/index.html" target="_top">netkiller debian 手劄</a>
<a href="http://netkiller.github.io/centos/index.html" target="_top">netkiller centos 手劄</a>
<a href="http://netkiller.github.io/freebsd/index.html" target="_top">netkiller freebsd 手劄</a>
<a href="http://netkiller.github.io/shell/index.html" target="_top">netkiller shell 手劄</a>
<a href="http://netkiller.github.io/security/index.html" target="_top">netkiller security 手劄</a>
<a href="http://netkiller.github.io/www/index.html" target="_top">netkiller web 手劄</a>
<a href="http://netkiller.github.io/monitoring/index.html" target="_top">netkiller monitoring 手劄</a>
<a href="http://netkiller.github.io/storage/index.html" target="_top">netkiller storage 手劄</a>
<a href="http://netkiller.github.io/mail/index.html" target="_top">netkiller mail 手劄</a>
<a href="http://netkiller.github.io/docbook/index.html" target="_top">netkiller docbook 手劄</a>
<a href="http://netkiller.github.io/version/index.html" target="_top">netkiller version 手劄</a>
<a href="http://netkiller.github.io/database/index.html" target="_top">netkiller database 手劄</a>
<a href="http://netkiller.github.io/postgresql/index.html" target="_top">netkiller postgresql 手劄</a>
<a href="http://netkiller.github.io/mysql/index.html" target="_top">netkiller mysql 手劄</a>
<a href="http://netkiller.github.io/nosql/index.html" target="_top">netkiller nosql 手劄</a>
<a href="http://netkiller.github.io/ldap/index.html" target="_top">netkiller ldap 手劄</a>
<a href="http://netkiller.github.io/network/index.html" target="_top">netkiller network 手劄</a>
<a href="http://netkiller.github.io/cisco/index.html" target="_top">netkiller cisco ios 手劄</a>
<a href="http://netkiller.github.io/h3c/index.html" target="_top">netkiller h3c 手劄</a>
<a href="http://netkiller.github.io/multimedia/index.html" target="_top">netkiller multimedia 手劄</a>
<a href="http://netkiller.github.io/perl/index.html" target="_top">netkiller perl 手劄</a>
<a href="http://netkiller.github.io/radio/index.html" target="_top">netkiller amateur radio 手劄</a>
<a href="http://netkiller.github.io/devops/index.html" target="_top">netkiller devops 手劄</a>
目錄
<a href="http://netkiller.github.io/journal/thread.php.html#idp57489856">1. 多線程環境安裝</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57624496">1.1. php 5.5.9</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57627904">1.2. 安裝 pthreads 擴充</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57630864">2. thread</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57633120">3. worker 與 stackable</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57636160">4. 互斥鎖</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57641888">4.1. 多線程與共享記憶體</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57644512">5. 線程同步</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57647872">6. 線程池</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57648512">6.1. 線程池</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57652448">6.2. 動态隊列線程池</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57655872">6.3. pthreads pool類</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57659040">7. 多線程檔案安全讀寫(檔案鎖)</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57663728">8. 多線程與資料連接配接</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57665248">8.1. worker 與 pdo</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57667920">8.2. pool 與 pdo</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57678128">8.3. 多線程中操作資料庫總結</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57681104">9. thread and zeromq</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57682416">9.1. 資料庫端</a>
<a href="http://netkiller.github.io/journal/thread.php.html#idp57685424">9.2. 資料處理端</a>
安裝php 5.5.9
<a href="https://github.com/oscm/shell/blob/master/php/5.5.9.sh">https://github.com/oscm/shell/blob/master/php/5.5.9.sh</a>
編譯必須啟用zts支援否則無法安裝 pthreads(--enable-maintainer-zts)
檢視pthreads是否已經安裝
什麼情況下會用到互斥鎖?在你需要控制多個線程同一時刻隻能有一個線程工作的情況下可以使用。
下面我們舉一個例子,一個簡單的計數器程式,說明有無互斥鎖情況下的不同。
我們使用檔案/tmp/counter.txt儲存計數器值,每次打開該檔案将數值加一,然後寫回檔案。當多個線程同時操作一個檔案的時候,就會線程運作先後取到的數值不同,寫回的數值也不同,最終計數器的數值會混亂。
沒有加入鎖的結果是計數始終被覆寫,最終結果是2
而加入互斥鎖後,隻有其中的一個程序完成加一工作并釋放鎖,其他線程才能得到解鎖信号,最終順利完成計數器累加操作
上面例子也可以通過對檔案加鎖實作,這裡主要講的是多線程鎖,後面會涉及檔案鎖。
在共享記憶體的例子中,沒有使用任何鎖,仍然可能正常工作,可能工作記憶體操作本身具備鎖的功能。
有些場景我們不希望 thread->start() 就開始運作程式,而是希望線程等待我們的指令。
$thread->wait();測作用是 thread->start()後線程并不會立即運作,隻有收到 $thread->notify(); 發出的信号後才運作
自行實作一個pool類
上面的例子是當線程池滿後執行start統一啟動,下面的例子是隻要線程池中有空閑便立即建立新線程。
pthreads 提供的 pool class 例子
檔案所種類。
共享鎖例子
共享鎖例子2
線上程池中連結資料庫
進一步改進上面程式,我們使用單例模式 $this->worker->getinstance(); 全局僅僅做一次資料庫連接配接,線程使用共享的資料庫連接配接
資料庫持久連結很重要,否則每個線程都會開啟一次資料庫連接配接,然後關閉,會導緻很多連結逾時。
應用場景,我使用觸發器監控資料庫某個表,一旦發現有改變就通知程式處理資料
使用方法
此程式涉及守候程序實作$this->daemon()運作後轉到背景運作,程序id儲存,程序的互斥(不允許同時啟動兩個程序),線程池連接配接數以及線程任務等等
<iframe id="dsq-2" style="width: 1775px; border-style: none !important; overflow: hidden !important; height: 547px !important;" title="disqus" src="http://disqus.com/embed/comments/?base=default&amp;disqus_version=2276213d&amp;f=netkiller&amp;t_u=http%3a%2f%2fnetkiller.github.io%2fjournal%2fthread.php.html&amp;t_d=php%20%e9%ab%98%e7%ba%a7%e7%bc%96%e7%a8%8b%e4%b9%8b%e5%a4%9a%e7%ba%bf%e7%a8%8b&amp;t_t=php%20%e9%ab%98%e7%ba%a7%e7%bc%96%e7%a8%8b%e4%b9%8b%e5%a4%9a%e7%ba%bf%e7%a8%8b&amp;s_o=default#2" frameborder="0" scrolling="no" width="100%" data-disqus-uid="2"></iframe>