官术网_书友最值得收藏!

第3章
Immutable Object(不可變對象)模式

3.1 Immutable Object模式簡介

在多線程共享變量的情況下,為了保證數據一致性,往往需要對這些變量的訪問進行加鎖。而鎖本身又會帶來一些問題和開銷。Immutable Object模式使得我們可以在不使用鎖的情況下,既保證共享變量訪問的線程安全,又避免引入鎖可能帶來的問題和開銷。

在多線程環境中,一個對象常常會被多個線程共享。在這種情況下,如果存在多個線程并發地修改該對象的狀態或者一個線程訪問該對象的狀態而另一些線程試圖修改該對象的狀態,則我們不得不做一些同步訪問控制以保證數據一致性。而這些同步訪問控制,如顯式鎖(Explicit Lock)和CAS(Compare and Swap)操作,會帶來額外的開銷和問題,如上下文切換、需要等待和ABA問題等。Immutable Object模式的意圖是通過使用對外可見的狀態不可變的對象(即Immutable Object),使得被共享對象“天生”具有線程安全性,而無須進行額外的同步訪問控制。這樣既保證了數據一致性,又避免了同步訪問控制所產生的額外開銷和問題,也簡化了編程。

所謂狀態不可變的對象,即一經創建,其對外可見的狀態就保持不變的對象,例如Java中的String和Integer。這一點固然容易理解,但還不足以指導我們在實際工作中運用Immutable Object模式。下面看一個典型的應用場景,這不僅有助于我們理解該設計模式,也有助于我們在實際環境中運用它。

一個車輛管理系統要對車輛的位置信息進行跟蹤,我們可以對車輛的位置信息建立如清單3-1所示的模型。

清單3-1 狀態可變的位置信息模型(非線程安全)

當系統接收到新的車輛坐標數據時,需要調用Location的setXY方法來更新位置信息。顯然,清單3-1中的setXY方法是非線程安全的,因為對坐標數據x和y的寫操作不是一個原子操作。在setXY方法被調用時,如果在x寫入完畢而y開始寫之前有其他線程來讀取位置信息,則該線程可能讀到一個被跟蹤車輛根本不曾經過的位置。為了使setXY方法具備線程安全性,我們需要借助鎖進行訪問控制。雖然被跟蹤車輛的位置信息總是在變化,但是我們也可以將位置信息建模為狀態不可變的對象,如清單3-2所示。

清單3-2 狀態不可變的位置信息模型

在使用狀態不可變的位置信息模型時,如果車輛的位置發生變動,則更新車輛的位置信息是通過替換整個表示位置信息的對象(即Location實例)來實現的[1],如清單3-3所示。

清單3-3 在使用狀態不可變對象的情況下更新車輛的位置信息

因此,所謂狀態不可變的對象并非指被建模的現實世界實體的狀態不可變,而是我們建模時的一種策略:現實世界實體的狀態總是在變化,但我們可以用狀態不可變的對象來對這些實體進行建模。

主站蜘蛛池模板: 朝阳县| 安多县| 安丘市| 原阳县| 左贡县| 吕梁市| 石台县| 当阳市| 沙洋县| 绥阳县| 精河县| 新竹市| 香河县| 行唐县| 香格里拉县| 濮阳县| 孝感市| 阜阳市| 宁武县| 尼玛县| 靖安县| 淮北市| 南开区| 中西区| 广河县| 遂宁市| 偃师市| 左贡县| 宿州市| 九江县| 铁岭市| 丁青县| 东乌珠穆沁旗| 台东市| 安溪县| 玛纳斯县| 庆云县| 沧源| 渑池县| 武冈市| 共和县|