物件都是由成員變數所組成的,如果它們全部都是原始型態(primitive type),那麼就構成了整個物件的 state
如下方程式碼所示:
public final class Counter {
private long value = 0;
public synchronized long getValue() {
return value;
}
public synchronized long increment() {
if(value == Long.MAX_SIZE) {
throw new IllegalStateException("counter overflow")
}
return ++counter;
}
}
上面是典型的 Java Monitor Pattern
Counter 這個類別只有一個 field,其物件的 state 就由它獨自組成
在這裡的 invariant 就是我遞增之後值要加一,不論在任何執行緒看到的結果都是如此
透過 synchronized 管控取值與遞增,可以確保此類別所建立的物件皆為執行緒安全
如果物件的成員變數包含了參考到其它物件的話,那物件的 state 就要連那些被參考到的物件的 state 也考量在內
舉例來說 LinkedList 所參考到的所有 Node 的 state 會是構成 LinkedList 本身的 state 的要素之一
同步的政策決定了如何與其 state 互動而不破壞 invariant,這通常是思考 Immutability, Thread Confinement, Locking 要透過什麼樣的組合來確保執行緒安全
執行緒安全就是在並行存取的時候還能保持不變量
物件與變數都有其值域,這個值域愈小,複雜度愈低,可以的話 final 就好
比方說上面的 Counter,正常來說 long 的值域是從 Long.MIN_VALUE 到 Long.MAX_VALUE,但在 Counter 中限制負值的存在,因此它的 invariant 就是其 state value 必須為正整數
此外,有的操作是有所謂的 post-condition 的,以上面的 Counter 當例子,如果現在的 value 是 17,那下一個正確的值只能是 18
評論