Quyền sở hữu chung hiếm khi có ý nghĩa
Câu trả lời này có thể hơi lạc lõng, nhưng tôi phải hỏi, có bao nhiêu trường hợp có ý nghĩa từ quan điểm của người dùng để chia sẻ quyền sở hữu ? Ít nhất là trong các lĩnh vực tôi đã làm việc, thực tế không có lĩnh vực nào vì nếu không, điều đó có nghĩa là người dùng không cần đơn giản xóa một thứ gì đó khỏi một nơi, nhưng xóa nó khỏi tất cả các chủ sở hữu có liên quan trước khi tài nguyên thực sự loại bỏ khỏi hệ thống.
Đó thường là một ý tưởng kỹ thuật cấp thấp hơn để ngăn chặn tài nguyên bị phá hủy trong khi một thứ khác vẫn đang truy cập vào nó, giống như một luồng khác. Thông thường khi người dùng yêu cầu đóng / xóa / xóa thứ gì đó khỏi phần mềm, thì nên xóa nó càng sớm càng tốt (bất cứ khi nào an toàn để gỡ bỏ) và chắc chắn không nên nán lại và gây rò rỉ tài nguyên miễn là ứng dụng đang chạy
Ví dụ, một tài sản trò chơi trong trò chơi video có thể tham chiếu một tài liệu từ thư viện tài liệu. Chúng tôi chắc chắn không muốn, giả sử, một sự cố con trỏ lơ lửng nếu tài liệu bị xóa khỏi thư viện tài liệu trong một luồng trong khi một luồng khác vẫn đang truy cập vào tài liệu được tham chiếu bởi tài sản trò chơi. Nhưng điều đó không có nghĩa là nó có ý nghĩa đối với tài sản trò chơi để chia sẻ quyền sở hữu tài liệu mà họ tham chiếu với thư viện tài liệu. Chúng tôi không muốn buộc người dùng xóa tài liệu khỏi cả thư viện tài sản và tài liệu. Chúng tôi chỉ muốn đảm bảo rằng các tài liệu không bị xóa khỏi thư viện tài liệu, chủ sở hữu duy nhất của tài liệu, cho đến khi các chủ đề khác kết thúc truy cập vào tài liệu.
Rò rỉ tài nguyên
Tuy nhiên, tôi đã làm việc với một nhóm trước đây bao gồm tất cả các thành phần trong phần mềm. Và trong khi điều đó thực sự có ích trong việc đảm bảo chúng tôi không bao giờ bị phá hủy tài nguyên trong khi các luồng khác vẫn đang truy cập vào chúng, thì cuối cùng chúng tôi đã nhận được phần rò rỉ tài nguyên .
Và đây không phải là những rò rỉ tài nguyên tầm thường mà chỉ làm đảo lộn các nhà phát triển, giống như một kilobyte bộ nhớ bị rò rỉ sau một phiên kéo dài một giờ. Đây là những rò rỉ sử thi, thường là hàng gigabyte bộ nhớ trong một phiên hoạt động, dẫn đến các báo cáo lỗi. Bởi vì bây giờ khi quyền sở hữu của tài nguyên đang được tham chiếu (và do đó được chia sẻ quyền sở hữu) trong số 8 phần khác nhau của hệ thống, thì chỉ mất một phần để không xóa tài nguyên để phản hồi người dùng yêu cầu xóa tài nguyên đó bị rò rỉ và có thể vô thời hạn.
Vì vậy, tôi chưa bao giờ là một fan hâm mộ lớn của GC hoặc tính tham chiếu được áp dụng ở bất kỳ quy mô rộng nào vì họ dễ dàng tạo ra phần mềm bị rò rỉ như thế nào. Những gì trước đây là một sự cố con trỏ lơ lửng, dễ dàng phát hiện biến thành một rò rỉ tài nguyên rất khó phát hiện, có thể dễ dàng bay theo radar thử nghiệm.
Tài liệu tham khảo yếu có thể giảm thiểu vấn đề này nếu ngôn ngữ / thư viện cung cấp những vấn đề này, nhưng tôi thấy khó có được một nhóm các nhà phát triển các kỹ năng hỗn hợp để có thể sử dụng nhất quán các tài liệu tham khảo yếu bất cứ khi nào thích hợp. Và khó khăn này không chỉ liên quan đến nhóm nội bộ, mà là với mọi nhà phát triển plugin duy nhất cho phần mềm của chúng tôi. Chúng cũng có thể dễ dàng khiến hệ thống rò rỉ tài nguyên bằng cách lưu trữ một tài liệu tham khảo liên tục đến một đối tượng theo cách gây khó khăn cho việc truy tìm lại plugin là thủ phạm, vì vậy chúng tôi cũng nhận được phần báo cáo lỗi của chúng tôi từ tài nguyên phần mềm của chúng tôi bị rò rỉ đơn giản vì một plugin có mã nguồn nằm ngoài tầm kiểm soát của chúng tôi không thể phát hành tài liệu tham khảo cho các tài nguyên đắt tiền đó.
Giải pháp: Trì hoãn, Loại bỏ định kỳ
Vì vậy, giải pháp của tôi sau này mà tôi đã áp dụng cho các dự án cá nhân mang lại cho tôi loại tốt nhất tôi tìm thấy từ cả hai thế giới là loại bỏ khái niệm đó referencing=ownership
nhưng vẫn trì hoãn việc phá hủy tài nguyên.
Kết quả là, bây giờ bất cứ khi nào người dùng làm điều gì đó khiến tài nguyên cần xóa, API được thể hiện dưới dạng chỉ xóa tài nguyên:
ecs->remove(component);
... Mô hình logic kết thúc người dùng theo cách rất đơn giản. Tuy nhiên, tài nguyên (thành phần) có thể không bị xóa ngay lập tức nếu có các luồng hệ thống khác trong giai đoạn xử lý của chúng, nơi chúng có thể truy cập cùng một thành phần.
Vì vậy, các luồng xử lý này sau đó mang lại thời gian ở đây và ở đó cho phép một luồng giống như trình thu gom rác thức dậy và " ngăn chặn thế giới " và phá hủy tất cả các tài nguyên được yêu cầu xóa trong khi khóa các luồng xử lý các thành phần đó cho đến khi hoàn thành . Tôi đã điều chỉnh điều này để khối lượng công việc cần thực hiện ở đây nói chung là tối thiểu và không cắt giảm đáng kể vào tốc độ khung hình.
Bây giờ tôi không thể nói đây là một số phương pháp đã được thử nghiệm và được chứng minh bằng tài liệu tốt, nhưng đó là thứ tôi đã sử dụng trong vài năm nay mà không bị đau đầu và không bị rò rỉ tài nguyên. Tôi khuyên bạn nên tìm hiểu các cách tiếp cận như thế này khi kiến trúc của bạn có thể phù hợp với loại mô hình đồng thời này vì nó ít nặng tay hơn so với GC hoặc đếm lại và không có nguy cơ rò rỉ tài nguyên này dưới radar thử nghiệm.
Một nơi mà tôi thấy việc đếm lại hoặc GC là hữu ích là cho các cấu trúc dữ liệu liên tục. Trong trường hợp đó, đó là lãnh thổ cấu trúc dữ liệu, tách biệt khỏi mối quan tâm của người dùng và thực sự có ý nghĩa đối với mỗi bản sao bất biến để có khả năng chia sẻ quyền sở hữu cùng một dữ liệu chưa được sửa đổi.