2012-01-12 38 views
47

Hãy xem xét hai loại cổ phiếu này:thu rác và tham chiếu vòng tròn

public class A 
{ 
    B b; 
    public A(B b) { this.b = b; } 
} 

public class B 
{ 
    A a; 
    public B() { this.a = new A(this); } 
} 

Nếu tôi đã học được thiết kế như trên, các đối tượng của các lớp học như vậy sẽ được thu thập bởi rác Collector (GC)?

Giả sử tôi làm điều này:

void f() 
{ 
    B b = new B(); 
} 

Trong phương pháp này, tôi tạo ra một thể hiện của B gọi b, và khi trở về phương pháp, b đi ra khỏi phạm vi, và GC sẽ có thể thu thập nó , nhưng nếu thu thập nó, nó sẽ phải thu a đầu tiên là thành viên của B và để thu a, trước tiên cần phải thu b là thành viên của A. Nó trở thành hình tròn. Vì vậy, câu hỏi của tôi là: là tham chiếu vòng tròn như vậy sẽ ngăn chặn GC thu thập các đối tượng?

  • Nếu có, thì làm cách nào để tránh sự cố này? Làm cách nào để đảm bảo rằng chúng tôi không có tham chiếu vòng tròn trong thiết kế lớp học của mình? Có bất kỳ công cụ (hoặc tùy chọn trình biên dịch) giúp chúng tôi phát hiện tham chiếu vòng tròn?
  • Nếu không, ở đâu và tại sao chúng tôi sử dụng WeakReference lớp học? Mục đích của nó là gì?
+1

Hãy xem tại đây http://stackoverflow.com/questions/400706/circular-references-cause-memory-leak –

+0

Ít nhất một cách hợp lý một trong các tham chiếu luôn luôn yếu: Trong ví dụ của bạn, rõ ràng 'A 'không thể phụ thuộc vào' B', bởi vì 'A' phải được tạo thành đầu tiên, là thành viên của' B', và vì vậy 'A' chỉ có thể giữ một tham chiếu yếu với' B'. Vì vậy, an toàn để tiêu diệt 'B' trước và sau đó là 'A'. Tranh luận đệ quy, mỗi chương trình máy tính phải như vậy. Không bao giờ có thể là * true *, phụ thuộc hoàn toàn đối xứng tròn. –

+0

@KerrekSB: Tôi đồng ý với logic đó. Nhưng điều đó được nhìn từ điểm sáng tạo. Liệu GC sẽ phân tích điều này (tức là mã trong mỗi phương pháp của các lớp như vậy, sau khi tất cả chỉ sau đó nó có thể đạt được tại kết luận đó)? Ý tôi là, nếu bạn thấy các vật thể sau khi chúng được tạo ra, thì có vẻ như rất có vấn đề. – Nawaz

Trả lời

74

Bộ thu gom .Net hoàn toàn có thể xử lý các tham chiếu vòng tròn. Các rất xem mức độ cao về cách thức thu gom rác hoạt động là ...

  • Bắt đầu với người dân địa phương, tĩnh học và các đối tượng GC gắn. Không ai trong số này có thể được thu thập
  • Đánh dấu mọi đối tượng có thể đạt được bằng cách vượt qua con của các đối tượng này
  • Thu thập mọi đối tượng không được đánh dấu.

Điều này cho phép tham khảo vòng tròn được thu thập tốt. Vì vậy, miễn là không ai trong số họ có thể truy cập từ một đối tượng được gọi là uncollectable thì tham khảo vòng tròn về bản chất là không liên quan.

Lưu ý: Tôi nhận ra tôi đã rời ra nhiều chi tiết thú vị trong để giữ cho câu trả lời này đơn giản và trực tiếp

+0

Nó sẽ không phải tốn kém tính toán –

25

Không, này sẽ không là một vấn đề bởi vì GC có thể xử lý Thông tư Tài liệu tham khảo

MSDN Says

Nếu một nhóm đối tượng có chứa tài liệu tham khảo với nhau, nhưng không ai trong số những đối tượng được tham chiếu trực tiếp hoặc gián tiếp từ ngăn xếp hoặc biến được chia sẻ, sau đó bộ sưu tập rác sẽ tự động xác nhận lại bộ nhớ.

+1

Và đó là điều làm cho ngôn ngữ này trở nên tuyệt vời! – Aggressor

5

Không có tham chiếu vòng tròn sẽ không ảnh hưởng đến thu gom rác, và nó sẽ được hoàn toàn có thể thu thập trường hợp của B.

Các nhà sưu tập rác biết rằng không ai có thể tham khảo trường hợp của B sau khi đi ngoài phạm vi, và do đó, không ai có thể sử dụng cá thể B để gián tiếp tham khảo A.

5

Một số câu trả lời đã giải thích rằng tham chiếu vòng tròn không phải là một vấn đề.

Đối với các tham chiếu yếu - lý do sử dụng chúng là lưu vào bộ nhớ cache.

Khi GC đi đối tượng cây phụ thuộc, anh bỏ qua các tham chiếu yếu. Nói cách khác, nếu tham chiếu duy nhất tới một đối tượng là một đối tượng yếu, nó sẽ được thu gom rác, nhưng nếu không có bộ sưu tập rác giữa việc tạo tham chiếu và cố gắng sử dụng, bạn vẫn có thể truy cập đối tượng.

Các vấn đề liên quan