預防勝於治療
不要share memory是最簡單規避multithreading coordination的方法!怎麼做?
confined to a single thread
例如限定某個物件只能在某個thread上執行,進而實現了"singlethreaded"的要求。不過這必須在program structure設計上著手,Java只能提供輔助性的class來達成thread confinement。不過這類的設計(稱為ad-hoc thread confinement)是很脆弱的,因為沒有語言層面的支援,純粹靠設計者的架構,通常用在UI Subsystem,讓UI access變成single threaded。
Stack confinement (within-thread, thread-local confinement)
local variable所在的記憶體scope會是同一個stack,所以宣告local variable就只有其包含的thread能access。這個有用到語言runtime結構的支持,所以比ad-hoc confinement好一些,可靠一些。在Java中,沒有任何方式可以share local primitive type variable across threads。
但是對local object reference來說,是有可能被publish出去給其他thread看到的。另外雖然在withi-thread confinement的限制中,使用non-thread safety不會造成問題,但是這邊又變成依賴programmer的記性和架構,這是不利的地方,除非能夠被明確的documented。
ThreadLocal
較為正式的做法是使用Java ThreadLocal class。簡單說來,就是某個object經過ThreadLocal包裹之後,每個thread都會有一個object copy,透過accessors來update或取得自己thread內的object,彼此互不干擾。
這通常是class中某個private static member,希望是可以在程式內是globally accessible,但是又希望每個thread有自己的值,例如每個thread有自己的global temporary buffer,random ID等等。
例如以下範例,每個thread會拿到自己的一份connection instance:
這個ThreadLocal object會存在Thread object裡面,當thread結束後,自然也會被garbage collected。
不過由於ThreadLocal通常用在global object,所以還是要遵守盡量不要使用global object的原則。
Immutable Object (Java final keyword)
stateless object出生就是天然thread-safe,不廢話!要做一個stateless class,其所有data members必須要是final,且沒有任何escape機會。
對了注意object reference immutable不等於object 真的immutable。“部分states immutable"的object還是比所有states都mutable的object來得少問題,盡量宣告自己的class field final。
沒有留言:
張貼留言