Làm cho tất cả các phương thức trên một lớp được đồng bộ hóa riêng lẻ sẽ không tạo một tập hợp (gọi chúng trong một nhóm) của các luồng phương thức đó an toàn. Bằng cách gói Iterator
trong một khối đồng bộ, bạn đang bảo vệ cá thể cụ thể của trình lặp đó khỏi phương thức riêng của nó được gọi là xen kẽ với các cuộc gọi khác bởi nhiều luồng.
Nếu tôi gọi .add()
khi nó là an toàn, nếu tôi cần phải gọi .add()
nhiều lần để hoàn thành một tuyên bố hợp lý, không có đảm bảo rằng ai đó đã không được thêm cái gì khác hoặc gỡ bỏ cái gì khác giữa .add()
cuộc gọi của tôi, trừ khi tôi chặn mọi thứ khác khỏi gọi .add()
(hoặc bất kỳ phương pháp nào khác) bằng cách synchronizing
trên biến đại diện cho bộ sưu tập.
Iterator
làm cho mutiple gọi đến các phương thức riêng lẻ trên bộ sưu tập, tất cả chúng phải được bao bọc trong một khối synchronized
để làm cho chúng hoạt động như một đơn transaction
các loại. Kiểm tra mã nguồn của việc thực hiện của Iterator
bạn sẽ thấy những gì tôi có ý nghĩa. Đây là mã nguồn cho List
nó làm cho nhiều cuộc gọi riêng lẻ đến việc triển khai cơ bản, vì vậy tất cả chúng cần phải được thực hiện theo thứ tự không bị gián đoạn bởi cùng một luồng để xác định.
@Override
public Iterator<A> iterator() {
if (tail == null)
return emptyIterator();
return new Iterator<A>() {
List<A> elems = List.this;
public boolean hasNext() {
return elems.tail != null;
}
public A next() {
if (elems.tail == null)
throw new NoSuchElementException();
A result = elems.head;
elems = elems.tail;
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
Các source cho AbstractList.iterator()
cho thấy thậm chí logic phức tạp hơn mà làm cho nhiều cuộc gọi.
Trình bao bọc tốt hơn là gói chúng trong Immutable
bộ sưu tập, sau đó bạn đảm bảo rằng không có gì khác có thể thay đổi bộ sưu tập cơ bản giữa các cuộc gọi.
Nguồn
2013-04-03 21:00:36
Bạn có ý nghĩa gì bởi "nhất thiết phải liên quan đến nhiều cuộc gọi phương thức riêng biệt"? – user697911
@ user697911: 'i.hasNext()' và 'i.next()' là hai cuộc gọi phương thức riêng biệt và không có cách nào để thực hiện 'Collections.synchronizedCollection' để đảm bảo rằng không có gì thay đổi ở giữa' i.hasNext() 'và' i.next() '. –
Vì vậy, concurrentHashmap sẽ giống nhau? Chúng ta cũng phải đồng bộ hóa concurrenthashamp trong lần lặp lại không? – user697911