2009-03-28 18 views
12

Có sự khác biệt nào về ý nghĩa của AtomicIntegerArrayAtomicInteger[] không? Và cái nào nhanh hơn để sử dụng? (điều duy nhất mà tôi nhận thấy là đầu tiên lấy ít không gian hơn, nhưng điều đó có nghĩa là mỗi kiểm tra lại kiểm tra các ranh giới của mảng, sao cho nó có thể làm chậm hơn?)AtomicIntegerArray vs AtomicInteger []

Edit: Trong một kịch bản có mảng được khởi tạo.

Trả lời

8

AtomicInteger[] sẽ yêu cầu một đối tượng trên mỗi phần tử. AtomicIntegerArray chỉ yêu cầu đối tượng AtomicIntegerArray và đối tượng mảng. Vì vậy, sử dụng sau này nếu có thể.

Chi phí kiểm tra giới hạn là khá nhỏ ngay cả đối với mảng thông thường. Điều quan trọng là truy cập vào dữ liệu trong cùng một dòng bộ nhớ cache từ nhiều bộ xử lý có thể gây ra các vấn đề hiệu suất đáng kể. Vì vậy, các đối tượng riêng biệt, hoặc cố ý tránh các yếu tố gần của một mảng, có thể giúp đỡ.

+0

Ai quan tâm đến kiểm tra giới hạn? Nếu bạn nhìn vào mã nguồn (rõ ràng), ví dụ, getAndSet nó tính toán địa chỉ cho cả get và compareAndSet (mặc dù tệ hơn thế này, hầu hết các bộ vi xử lý có thể thực hiện get-and-set mà không có cas). –

+0

tnx (không thấy đoạn thứ hai của bạn ở đó) Vì vậy, có thể không tốt để tạo tất cả các đối tượng cùng một lúc? (hoặc với một số thứ tự ngẫu nhiên?) – Sarmun

+0

(Tôi đã chỉnh sửa nhanh.) Tạo đối tượng tại các thời điểm khác nhau sẽ không giúp ích vì GC sẽ sắp xếp lại chúng. Một trong các lớp trong java.util.concurrent đi xa hơn để thêm nhiều padding (trong các phiên bản gần đây). Nó sẽ dễ dàng hơn và rõ ràng hơn để thêm các phần tử đệm vào AtomicIntegerArray, chỉ cần dịch chuyển sang trái. –

0

Tôi đồng ý với đoạn đầu tiên Tom Hawin của ...

AtomicInteger [] sẽ đòi hỏi một đối tượng cho mỗi phần tử. AtomicIntegerArray chỉ yêu cầu đối tượng AtomicIntegerArray và một đối tượng mảng. Vì vậy, sử dụng sau này nếu có thể.

... nhưng cũng cần lưu ý rằng AtomicInteger [] không phải là chủ đề an toàn. Cụ thể, các tham chiếu của mảng đối với các đối tượng AtomicInteger riêng lẻ có thể hoặc có thể không chính xác nếu được truy cập từ nhiều luồng. Việc đồng bộ hóa quyền truy cập vào chính đối tượng mảng sẽ loại bỏ vấn đề này.

+2

Điểm về Atomic * là bạn tránh đồng bộ hóa. Phương pháp giả định sử dụng AtomicInteger [] là tạo tất cả các AtomicIntegers một lần và chỉ sau đó xuất bản mảng một cách an toàn. –

+1

Tôi đồng ý. Tôi không ủng hộ sử dụng AtomicInteger [], chỉ cần lưu ý sự khác biệt, đó là những gì các câu hỏi về :) –

4
  • AtomicInteger [] là một dãy số nguyên an toàn.
  • AtomicIntegerArray là một chuỗi các số nguyên an toàn.
2

Bên dưới, AtomicInteger và AtomicIntegerArray thường sử dụng cùng một API mức thấp để thực hiện đọc, viết và các hoạt động CAS khác. (Ví dụ, OpenSDK 7 sử dụng sun.misc.Unsafe để thực hiện các hoạt động CAS trong cả hai lớp.) Vì vậy, có rất ít lợi ích về hiệu suất khi sử dụng AtomicInteger []. Như bạn đã lưu ý, việc sử dụng AtomicIntegerArray không có lợi thế đáng kể về bộ nhớ.

Trên một lưu ý thực tế, việc sử dụng sau này giải phóng bạn khỏi việc phải xây dựng tất cả các phiên bản AtomicInteger của bạn. Hãy nhớ rằng bạn không thể phân bổ một cách ngây thơ một cách ngây thơ vì lý do đồng thời; bạn sẽ phải phân bổ trước hoặc sử dụng một số cơ chế xuất bản an toàn. Vì vậy, ngoài lợi thế bộ nhớ, mã của bạn còn sạch hơn.

On Tương tự, nếu bạn có một loạt các đối tượng với các thành viên AtomicInteger, ví dụ:

class ReadCounter { 
    private final String _fileName; 
    private final AtomicInteger _readCount; 
    ... 
} 

private final Map<String, ReadCounter> _counterByName = ...; 

Sau đó, bạn có thể đạt được những cải thiện bộ nhớ tương tự bằng cách mô hình hóa các biến thành viên _readCount như một volatile int và sử dụng AtomicIntegerFieldUpdater.

+0

Ở mức giá thấp hơn tốc độ cho các hoạt động updater (mặc dù nhận được và thiết lập là nhanh). Đôi khi nó có giá trị mở rộng từ nguyên tử * như một hack tiết kiệm bộ nhớ. –

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