Một điểm quan trọng chưa được đề cập là việc có trạng thái của một đối tượng là có thể thay đổi làm cho nó có thể có danh tính của đối tượng gói gọn trạng thái đó là bất biến.
Nhiều chương trình được thiết kế để mô hình hóa những thứ trong thế giới thực vốn có thể thay đổi. Giả sử rằng vào lúc 12:51 sáng, một số biến AllTrucks
giữ tham chiếu đến đối tượng # 451, là gốc của cấu trúc dữ liệu cho biết hàng hóa nào được chứa trong tất cả các xe tải của một đội tàu tại thời điểm đó (12:51 sáng) và một số biến BobsTruck
có thể được sử dụng để có được một tham chiếu đến đối tượng # 24601 điểm đến một đối tượng cho biết hàng hóa nào được chứa trong xe tải của Bob tại thời điểm đó (12:51 sáng). Vào lúc 12:51 sáng, một số xe tải (bao gồm cả Bob) được tải và dỡ tải, và cấu trúc dữ liệu được cập nhật để AllTrucks
giờ đây sẽ có tham chiếu đến cấu trúc dữ liệu cho biết hàng hóa có trong tất cả các xe tải vào lúc 12:51 sáng.
Điều gì sẽ xảy ra BobsTruck
?
Nếu thuộc tính 'hàng hóa' của mỗi đối tượng xe tải là bất biến, thì đối tượng # 24601 sẽ mãi mãi đại diện cho trạng thái mà xe tải của Bob có lúc 12:51 sáng. Nếu BobsTruck
giữ tham chiếu trực tiếp đến đối tượng # 24601, thì trừ khi mã cập nhật AllTrucks
cũng xảy ra để cập nhật BobsTruck
, nó sẽ ngừng thể hiện trạng thái hiện tại của xe tải Bob. Lưu ý thêm rằng trừ khi BobsTruck
được lưu trữ trong một số dạng đối tượng có thể thay đổi, cách duy nhất mà mã cập nhật AllTrucks
có thể cập nhật sẽ là nếu mã được lập trình rõ ràng để làm như vậy.
Nếu một người muốn có thể sử dụng BobsTruck
để quan sát xe tải của Bob trong khi vẫn giữ cho mọi vật thể không bị biến đổi, thì người ta có BobsTruck
thể là một chức năng bất biến, với giá trị AllTrucks
có hoặc có tại bất kỳ thời điểm cụ thể nào, sẽ mang lại trạng thái cho xe tải của Bob thời điểm đó Người ta thậm chí có thể có một cặp chức năng bất biến - một trong số đó sẽ như trên, và một trong số đó sẽ chấp nhận tham chiếu đến trạng thái hạm đội và trạng thái xe tải mới, và trả lại tham chiếu đến trạng thái hạm đội mới phù hợp với cái cũ, ngoại trừ xe tải của Bob sẽ có trạng thái mới.
Thật không may, việc phải sử dụng một chức năng như vậy mỗi khi muốn truy cập vào trạng thái xe tải của Bob có thể trở nên khá khó chịu và cồng kềnh. Một cách tiếp cận khác là nói rằng đối tượng # 24601 sẽ luôn luôn và mãi mãi (miễn là bất cứ ai có tham chiếu đến nó) đại diện cho trạng thái hiện tại của xe tải Bob. Mã sẽ muốn liên tục truy cập vào trạng thái hiện tại của xe tải Bob sẽ không phải chạy một số chức năng tốn thời gian - nó có thể chỉ cần thực hiện chức năng tra cứu một lần để tìm ra đối tượng # 24601 là xe tải của Bob, và sau đó chỉ đơn giản là truy cập vào đối tượng đó bất cứ lúc nào nó muốn thấy trạng thái hiện tại của xe tải Bob.
Lưu ý rằng cách tiếp cận chức năng không phải là không có lợi thế trong môi trường đơn luồng hoặc trong môi trường đa luồng, trong đó các luồng sẽ chủ yếu chỉ quan sát dữ liệu thay vì thay đổi nó. Bất kỳ luồng quan sát nào sao chép tham chiếu đối tượng có trongAllTrucks
và sau đó kiểm tra các trạng thái xe tải được đại diện qua đó sẽ thấy trạng thái của tất cả các xe tải tại thời điểm mà nó lấy tham chiếu. Bất cứ khi nào một chủ đề quan sát muốn xem dữ liệu mới hơn, nó có thể lấy lại tham chiếu. Mặt khác, việc toàn bộ trạng thái của hạm đội được đại diện bởi một đối tượng bất biến duy nhất sẽ loại trừ khả năng hai luồng cập nhật đồng thời các xe tải khác nhau, vì mỗi luồng nếu để lại các thiết bị của chính nó sẽ tạo ra một đối tượng "trạng thái hạm đội" mới bao gồm trạng thái mới của xe tải của nó và trạng thái cũ của nhau. Tính chính xác có thể được đảm bảo nếu mỗi luồng chỉ sử dụng CompareExchange
để cập nhật AllTrucks
nếu nó không thay đổi và phản hồi không thành côngCompareExchange
bằng cách tạo lại đối tượng trạng thái của nó và thử lại thao tác, nhưng nếu nhiều hơn một luồng cố gắng thực hiện thao tác ghi đồng thời, hiệu năng thường sẽ tệ hơn so với việc tất cả việc ghi được thực hiện trên một luồng; càng nhiều luồng cố gắng hoạt động đồng thời như vậy, hiệu suất sẽ càng tệ.
Nếu các đối tượng xe tải riêng lẻ có thể thay đổi nhưng có danh tính bất biến , kịch bản đa luồng trở nên sạch hơn. Chỉ một luồng có thể được phép hoạt động tại một thời điểm trên bất kỳ xe tải nào, nhưng các luồng hoạt động trên các xe tải khác nhau có thể làm như vậy mà không bị can thiệp. Mặc dù có nhiều cách người ta có thể mô phỏng hành vi đó ngay cả khi sử dụng các đối tượng không thay đổi (ví dụ: người ta có thể định nghĩa các đối tượng "AllTrucks" để cài đặt trạng thái của xe tải thuộc XXX cho SSS sẽ chỉ cần tạo một đối tượng có nội dung "Kể từ [Thời gian], trạng thái của xe tải thuộc [XXX] hiện là [SSS], trạng thái của mọi thứ khác là [Giá trị cũ của AllTrucks] ". Tạo ra một đối tượng như vậy sẽ đủ nhanh để ngay cả khi có sự tranh chấp, aCompareExchange
vòng lặp sẽ không mất nhiều thời gian. Mặt khác, sử dụng cấu trúc dữ liệu như vậy sẽ làm tăng đáng kể lượng thời gian cần thiết để tìm một chiếc xe tải của một người cụ thể. Sử dụng các đối tượng có thể thay đổi với danh tính bất biến sẽ tránh được vấn đề đó.