code

2017年1月19日 星期四

Java Concurrency 6 - Don't Share!

預防勝於治療

不要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。


沒有留言:

張貼留言