2015-11-13 79 views
0

將帖子PHP多線程 - 它是安全

背景:我在linux下一個CLI應用程序中使用並行線程包考慮。我發現了很多關於線程安全狀態的激烈辯論,並且由於許多php函數固有的非線程安全性,它看起來像是要避免的。

但是從this docs page:「線程安全通過在每個線程中創建一個本地存儲副本,以便數據不會與另一個線程衝突」。這似乎「解決」了問題並且過時了大部分舊信息(即使實際的php代碼沒有被重寫)。

問題:

一)具有當前的PHP線程安全模型已經證明不安全以任何理由?

b)必須有速度和內存命中加載到每個線程的解釋器 - 任何統計數據可用?

請:沒有意見,受過教育或其他方式,只是可證明的,最新的數據。

+0

你的第二個問題是基於一個無效的假設:線程通常共享一個內存空間,所以解釋器不是「加載到每個線程中」,而是一次進入進程。對於任何可能的問題,請檢查錯誤跟蹤系統。 –

+0

@Ulrich你是指生成線程的'進程',還是'進程'是每個線程?爲每個線程使用一個單獨的解釋器副本似乎可以解決非線程安全的功能問題。沒有? – Berniev

+1

術語「過程」在計算中具有特定的含義,例如檢查。 SO的過程標籤文檔,就是我的意思。 –

回答

4

完全披露:我是內部的貢獻者,我寫了pthreads。

帶有線程模型的PHP的第一個版本是在2000年5月22日PHP4的到來。

有牙齒問題,根本不是由模型理論造成的,而是由打破模型的代碼引起的;例如,調用非重入函數。

調用非可重入函數仍然可能會造成問題;調用代碼使用的模型無關緊要,如果被調用者將忽略它,並執行諸如使用全局共享或靜態狀態的操作。

在2000年,圖書館或功能不像今天這樣普遍,因此無法重新進入。主要原因是未嵌入式多核系統一般在晚些時候才被髮布。

如今,圖書館的默認版本是可重入的,或者在2000年提供了可重入版本。

這些初期出現的問題是在2015年

PHP是由許多模塊的一個遙遠的記憶,從分配器和執行者,在標準庫,和一切圍繞第三方瘦包裝擴展庫。

線程安全性實際上是通過確保每個線程具有所有模塊全局變量的唯一副本來實現的。

所以線程完全在不同的內存區域運行,這根本不像一般的多線程應用程序。

他們可以在技術上共享,但他們不:沒有分享。

反對者最終能夠睡覺嗎?

,沒有爭議; PHP有一個強大的,經過驗證的線程安全模型。

必須有速度和內存命中加載到每個線程的解釋器 - 他們是否明顯?

是的,你可以測量它,沒有任何事情是免費的。

但是,另一種方法是在線程之間共享模塊全局變量。

模塊全局變量的頻率非常高,引用了分配,釋放,打印,獲取對象,獲取資源以及一百萬件事情。

如果它們是共享的,您需要同步對它們的訪問,除了爲每個請求提供大量(大約數百萬到數千萬)額外指令外,還引入了巨大的鎖爭用。

該替代方案將癱瘓PHP。

在現實中,一個單獨的翻譯的費用是只是初始化單獨的模塊全局的成本,當你考慮替代方案,它是非常便宜

pthreads在任何時候都不會中斷PHP的線程模型,即使看起來,它也不能。

這就是所有這些。

+0

共享類靜態或功能靜態對象嗎?要點是人們仍然編寫非重入代碼:'function getFoo(){static $ foo = null; if(!$ foo)$ foo = allocateFoo();返回$ foo; }'。如果它是共享的,它不是線程安全的。如果不共享,則將「Foo」分配兩次。 –

+0

@Joe非常感謝您的支持,我相信您已經擁有了!在許多小時的研究中,我發現糟糕的新聞壓倒了你的其他SO條目,但手冊頁的線索引發了新的興趣。因此,這尋求〜可證明的問題〜。無論如何,這個問題已被關閉,所以我們永遠不會知道。另外,更詳細的文檔可以讓像我這樣的新手更容易地過濾BS。 – Berniev

+0

@UlrichEckhardt沒有共享,「無分享」...所有的php函數實際上都是可重入的,因爲執行它沒有編譯的函數的任何線程實際上都在執行該函數的副本。不僅僅用於pthreads,而且用於任何緩存代碼:Opcache/APC等等......這意味着''foo'''被分配了'''n'''次,其中'''n'''是執行該函數的線程數,因爲'''foo'''來自任何上下文都不能被共享...... –