まだ言及されていない主要な点は、オブジェクトの状態を可変にすると、その状態をカプセル化するオブジェクトのアイデンティティを不変にすることができるということです。
多くのプログラムは、本質的に可変である実世界のものをモデル化するように設計されています。12:51 amに、変数(AllTrucks
オブジェクト#451への参照)を保持すると仮定します。オブジェクト#451は、その瞬間(12:51 am)にフリートのすべてのトラックに含まれる貨物を示すデータ構造のルートです。BobsTruck
オブジェクト#24601への参照を取得するために使用して、その時点(12:51 am)にボブのトラックにどの貨物が含まれているかを示すオブジェクトを指すことができます。12:52 amに、一部のトラック(ボブのトラックを含む)が積み降ろされ、データ構造が更新さAllTrucks
れ、12:52amの時点で貨物がすべてのトラックにあることを示すデータ構造への参照が保持されます。
何が起こるのBobsTruck
?
各トラックオブジェクトの「cargo」プロパティが不変の場合、オブジェクト#24601は、ボブのトラックが午前12時51分に持っていた状態を永久に表します。BobsTruck
オブジェクト#24601への直接参照を保持している場合、更新するコードAllTrucks
がupdate BobsTruck
にも発生しない限り、ボブのトラックの現在の状態を表すのをやめます。さらにBobsTruck
、何らかの形式の可変オブジェクトに格納されていない限り、更新するコードが更新AllTrucks
できる唯一の方法は、コードがそうするように明示的にプログラムされている場合です。
BobsTruck
すべてのオブジェクトを不変に保ちながらボブのトラックの状態を観察できるようにしたい場合は、特定の時点でのBobsTruck
値AllTrucks
または特定の時点での値を指定すると、ボブのトラックの状態を取得する不変の関数を使用できますその時。1つは不変の関数のペアを保持することもできます。1つは上記のようになり、もう1つは艦隊状態と新しいトラック状態への参照を受け入れ、新しい艦隊状態への参照を返します。ボブのトラックが新しい状態になることを除いて、古いものと一致しました。
残念ながら、ボブのトラックの状態にアクセスするたびにそのような機能を使用しなければならないことは、かなり面倒で扱いにくいものになる可能性があります。別のアプローチは、オブジェクト#24601が常にそして永遠に(誰かがそれへの参照を保持している限り)ボブのトラックの現在の状態を表すということです。ボブのトラックの現在の状態に繰り返しアクセスするコードは、時間のかかる関数を毎回実行する必要はありません。オブジェクト#24601がボブのトラックであることを確認するために1回だけルックアップ関数を実行できます。ボブのトラックの現在の状態を見たいときはいつでもそのオブジェクトにアクセスします。
機能的なアプローチは、シングルスレッド環境、またはスレッドがデータを変更するのではなく単に監視するだけのマルチスレッド環境で利点がないわけではないことに注意してください。に含まれるオブジェクト参照をコピーするオブザーバースレッドAllTrucks
そして、それによって表されるトラックの状態を調べると、参照を取得した瞬間のすべてのトラックの状態が表示されます。オブザーバスレッドは、いつでも新しいデータを確認したい場合に、参照を再取得できます。一方、フリートの状態全体を単一の不変オブジェクトで表すと、2つのスレッドが異なるトラックを同時に更新する可能性がなくなります。各スレッドが独自のデバイスに残されると、新しいフリート状態オブジェクトが生成されるためです。トラックの新しい状態と他のすべての古い状態。各スレッドが、変更されていない場合にのみCompareExchange
更新に使用AllTrucks
し、失敗に応答する場合、正確性が保証される場合がありますCompareExchange
状態オブジェクトを再生成して操作を再試行しますが、複数のスレッドが同時書き込み操作を試みると、一般にすべての書き込みが単一のスレッドで行われた場合よりもパフォーマンスが低下します。このような同時操作を試行するスレッドが多いほど、パフォーマンスが低下します。
個々のトラックオブジェクトが可変であるが、不変のIDを持っている場合、マルチスレッドシナリオはよりクリーンになります。特定のトラックで一度に動作できるスレッドは1つだけですが、異なるトラックで動作するスレッドは干渉なしで動作できます。不変オブジェクトを使用する場合でも、このような動作をエミュレートする方法があります(たとえば、「AllTrucks」オブジェクトを定義して、XXXに属するトラックの状態をSSSに設定するには、「As of [Time] [XXX]に属するトラックの状態は[SSS]になり、他のすべての状態は[古い値のAllTrucks] "になります。このようなオブジェクトの生成は、競合が存在する場合でも十分に高速です。CompareExchange
ループは長くかかりません。一方、このようなデータ構造を使用すると、特定の人のトラックを見つけるのに必要な時間が大幅に増加します。不変のIDを持つ可変オブジェクトを使用すると、その問題を回避できます。