Thread-safe class
可以定義成:如果一個class instance在多個threads存取他的過程中,所有可能的執行緒的存取順序都能產出spec定義的行為,而且存取他的threads並不用做任何synchronization之類的工程,那這個class就可以說是thread safe。Stateless object永遠是thread-safe的
下面這個class只有一個method,而且沒有任何data member,換句話說,不論是class instance或是method裡面都沒有state的存在,這讓access這個class instance的thread彷彿在access不同的instance,所以是一個thread safe class:Non Atomic operation is not thread-safe
如果把上面的class加入一個state來計算request數目,我們可能會這樣做:++count這行程式實際上不是atomic operation!所謂atomic operation是指單一thread會完整執行完畢產生預期效果後,此operation才會換其他thread執行。
++count實際上是三個CPU指令:(1)讀取couont (2)計算新的count值 = count+1 (3)寫入新的count值,這是所謂的read-modify-write operation。
兩個thread如果執行這個method,可能會產生以下的非預期狀況:
Race condition
一個多執行緒程式,如果必須要依賴時間點的巧合才能產生預期結果的話,那代表可能有race condition。一種常見的race condition pattern是check-then-act的設計:透過觀察某一個事件的發生,去決定要進行的動作。問題出在多執行緒的程式執行中,這個觀察到的事件,可能在要進行動作的時候就不成立了,主要是因為觀察和動作並非atomic。一個常見的check-then-act設計是singleton pattern :
singleton pattern通常利用lazy initialization的技巧來達成單一instance的目的,但是由於getInstance()並沒有impelemnt成atomic operation,所以會產生race condition。
利用現有Thread-safe object來達成thread-safety
上面的UnsafeCountingFactorizer class,我們可以利用java提供的AtomicLong來取代long,進而保證thread-safety。這是一個快速的解決方案,能如此達成的話,盡量先採取這個approach。
沒有留言:
張貼留言