8
Why Johnny Can’t Write Multithreaded Programs (blog.smartbear.com)
IngramChen 積分 13 編輯於

拜讀完了,說的真是好啊。

If a multithreaded program is unreliable it’s most likely due to the same reasons that single-threaded programs fail: The programmer didn’t follow basic, well known development practices.

單 thread 的程式很多人都寫的零零落落了,去寫多 thread 只是更慘而已。有些人是不知上進,有些人則是不曉得可以改進,就是整天以 dirty hack 的方式去處理多 thread 帶來的問題。

If you used a lock, you probably did something wrong.

其實有點經驗的開發者是知道 global state 不好的,不過遇到多 thread 的程式,常 不小心 地就導入 synchronized/lock ,但殊不知 lock 本質上就是一種 global state (就保護某個很多地方都可以存取的狀態啊)。在單 thread 程式裡學會要避免 global 變數,那開發者也應該要學會 本能地 避開 lock。

我個人開發過許多 Java server 的程式,不少是 concurrent 的,我是那種死都不寫 new Thread() 派的,只用更高階的 Executor Framework1 ,一來是真的吃過 lock 的苦頭,二來使用高階的 library,它會給你 限制 ,限制你只能用某些方式使用多 thread 解決問題。大多數的情況下這樣的限制會引導你設計出更容易維護、更好理解的 concurrent 程式。

我也寫過一陣子 Actor ( Akka2 ) ,它是另一個方向發展的高階 library,概念上主要是 event driven,以及 actor 階層的管理。雖然 Actor 將 thread 藏起來了,開發上就是處理一連串的 event,但其實設計時你還是要了解用了多少 thread,有多少會被 block,而有 block 的部份就要分配額外的 thread pool 給它、調整 mailbox,不然資源還是會被耗盡。

Executor/Actor 兩種各有擅長解決的問題。Executor 適合做運算,做那種 state 閃一下就消失的工作 (比方說每個 request,用完即丟)。而 Actor 則適合有一大堆迷你的 state 的任務 (比方說每個連線的使用者,每個人都存了一些狀態),而且 Actor 模型也適合導入 state machine,可以避免複雜度隨著 state 變多而變得更複雜。兩者都能勝任各種 concurrent 的問題,實在是沒有理由再去碰最低階的 synchronize/lock。

但有時候難免還是會寫到 lock,這時的策略就是 抄書 ,書上的專家說怎麼寫才是對的,那就不要亂改。在 Java 界我推薦 Java Concurrency in Practice3 ,相信我,這本不會讓你失望的。如果你認真念完這本,就會了解為什麼我會建議八股地抄書了,在低階的多 thread 的世界,實在是不能以常理、直覺去理解。

開發者對待 lock,就要跟對待 密碼學4 一樣,抱著敬畏的心態,小心翼翼的地處理。