câu trả lời khác đã xác định được vấn đề:
Các vòng lặp cho bộ sưu tập đồng bộ chưa đồng bộ. Trong thực tế, chúng đơn giản là các trình vòng lặp được trả về bởi các đối tượng thu thập bên trong các lớp trình bao bọc.
Nhiều lớp thu thập (bao gồm ArrayList
) sử dụng cơ chế không nhanh để phát hiện các sửa đổi đồng thời trong khi lặp lại. Hành vi này được ghi rõ trong javadocs cho các lớp tương ứng. Đây là những gì bạn đang nhìn thấy.
Không phải tất cả các lớp thu thập đều làm điều này.Ví dụ, nhiều lớp sưu tập java.util.Concurrent...
cho phép sửa đổi đồng thời trong khi lặp lại, nhưng thư giãn ngữ nghĩa của chuỗi lặp để kết quả sửa đổi có thể hoặc không thể hiển thị trong đối tượng được trình lặp lặp lại.
javadoc cho số Collections.synchronizedList()
giải thích cách đồng bộ hóa trình lặp. Về cơ bản bạn làm điều này:
List list = Collections.synchronizedList(new ArrayList());
...
synchronized (list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
(Ngoài: bình thường nó không phải là an toàn để giả định rằng làm một cái gì đó như thế này sẽ làm việc Về lý thuyết, trong danh sách đồng bộ có thể sử dụng một đối tượng khóa riêng, và báo cáo kết quả synchronized
sẽ không khóa. Tuy nhiên các javadocs nói rằng đây là những gì cần làm trong trường hợp này ... vì vậy nó là an toàn.)
Vấn đề với việc đó là khóa bộ sưu tập tạo ra một nút cổ chai tiềm năng đồng thời. Cách thay thế là sử dụng cấu trúc dữ liệu sao chép vào ghi nội bộ sao chép các phần liên quan của bộ sưu tập. Cách tiếp cận này có nghĩa là một trình lặp sẽ thấy một ảnh chụp nhanh của bộ sưu tập. Sửa đổi có thể được thực hiện cho bộ sưu tập đồng thời với một lần lặp, nhưng trình lặp không nhìn thấy chúng. Vấn đề với copy-on-write là những sửa đổi có khả năng đắt hơn rất nhiều.
Cuối cùng, bạn cần phải cân bằng các đặc tính và chi phí của các loại bộ sưu tập khác nhau thay đổi đồng thời wrt so với yêu cầu thực tế của bạn. Bạn có thể thoát khỏi trình vòng lặp không nhìn thấy tất cả các sửa đổi đồng thời không?
Nguồn
2010-09-28 15:46:38
tôi có thể nhận được điểm của bạn tôi không thể sử dụng trình vòng lặp để truy cập arrayList đồng bộ. – Lalchand