2010-08-19 98 views

回答

17

在Erlang中執行狀態的單位不是一個線程,而是一個進程。是的,這是一個在線程之上實現的輕量級進程;但它更像是一個過程而不是一個線程。

重點是進程不共享狀態,它們傳遞消息;而線程默認分享一切,並且必須進行仲裁以避免混亂。

因此,您不需要線程安全,因爲您不使用線程。

+0

+1完全正確 – 2010-08-19 17:10:55

+2

但你確實需要「過程安全」:) – 2010-08-20 07:48:04

1

聲明:我幾乎不知道Erlang。用一粒鹽給我看。

純粹功能語言(顯然)只允許「純」功能。維基說,純粹的功能總是線程安全的,從而證實了我對這個話題的直覺。

但我不知道Erlang是否是純粹的功能(wiki暗示否則,所以我猜這不是)。也許它使用其他方式來實現線程安全。無論如何,它的數據結構(大多是?獨佔的?)是不可變的,因此它本質上是線程安全的。作爲一種功能性語言,至少慣用的Erlang代碼不會使用(muc?any?)全局變量,而是使用純函數。這些是線程安全的。但事情I/O可能仍然是一個問題......如果一個Erlang程序同時讀取和寫入文件,這樣的代碼不可能不是線程安全的。但大多數情況下,由於不可變的數據結構等原因,你會好起來的。

5

哈維爾是對的。

但是,我想添加一些它之前吸引我的東西。如果您正在使用內置驅動程序或nif,它可能不再是線程安全的。這似乎很明顯,因爲驅動程序或nif將使用C或C++代碼,但值得一提的是。所以你不能僅僅因爲使用Erlang而完全忽略線程安全。

3

否參見Erlang Style Actors Are All About Locking。在功能語言中實現線程安全性要容易得多,但您需要考慮它。

我剛開始學習線程安全性。這讓我的代碼更加防守,可能太防守。

請注意,在這種情況下,您很可能仍然錯誤。共享一切併發是非常非常難以得到正確的除了最微不足道的例子。

+0

有趣的文章,但我不認爲「線程安全」意味着死鎖免費。在Java/C#世界中,它通常意味着一個受到保護的對象免受併發更新,並且可以安全地在多線程環境中使用。 OP對防禦性編程的參考提出了相同的觀點。 – dsmith 2010-08-24 17:42:16

+2

但你是對的。新的Erlang程序員不能忽視死鎖的可能性。但是關於這篇文章的有趣之處在於,它沒有停止虛擬機,而是一種「打破」死鎖的方式。你打開一個Erlang shell並將消息推送到鎖定的進程。 – dsmith 2010-08-24 17:47:29

2

不,您仍然需要考慮Erlang中的線程安全性,但問題要簡單得多。

我讀了an article,其中作者指出您的消息API可能導致線程問題。這個例子圍繞着一個銀行賬戶。他的初始消息API具有GET和SET操作。一些想要存入$ 100的代碼會獲取當前值,並將其加100,然後設置結果。當然,這隻有在單個進程訪問銀行賬戶時纔有效。一旦兩個過程操縱平衡,所有投注都關閉。他的解決方案是將消息API更改爲DEPOSIT和WITHDRAW(他實際上使用了一條消息 - 更新 - 但你明白了)。這會導致交互採用原子語義 - 監聽過程一次只能處理一次存款或提款,並會阻止其他請求,直到第一次完成。

值得注意的是,這個問題與共享內存問題基本相同。 (如果我們使用GET和SET消息與進程交互,我們基本上創建了一些共享內存)。另一位博主compares ets to shared memory也是如此。然而,只要你明白你已經引入了共享內存結構,並規定了對共享內存的訪問權限,你就不應該有任何線程問題(當然,除了死鎖之外)。