2009-08-29 43 views
5

Với đoạn mã sau:Cài đặt an toàn cho chủ đề của biến (Java)?

public class FooBar { 

public static volatile ConcurrentHashMap myConfigData = new ConcurrentHashMap();  

} 

public class UpdaterThread implements Runnable { 

run { 

//Query the Data from the DB and Update the FooBar config Data 
FooBar.myConfigData = ConfigDataDAO.getLatestConfigFromDB(); 
} 
} 

Các Chủ đề-Class sẽ cập nhật myConfigData Membervariable thường xuyên (thông qua một Executor mỗi 5 phút). Là thiết lập của myConfigData trong luồng chủ đề "bên ngoài" (nguyên tử), hay tôi phải đồng bộ hóa mọi hoạt động Đọc và Ghi vào Biến myConfigData?

EDIT: Câu hỏi đặt ra là liệu ConcurrentHashMap có phải là chủ đề an toàn không (theo javadoc) mà đúng hơn là cài đặt Bản ConcurrentHashMap trong biến Thành viên myConfigData. Biến này có thể được đọc và viết "cùng một lúc" bởi một số luồng nên câu hỏi là liệu cài đặt có phải là nguyên tử hay không. Tôi nghĩ rằng điều này có thể được khái quát hóa là "Thiết lập của một biến tham chiếu Java có nguyên tử hay không?".

(Tôi cũng đã làm cho nó dễ bay hơi này là một vấn đề khác nhau và không có gì để làm với số nguyên tử - câu hỏi của tôi - mà là "tầm nhìn trong chủ đề khác" và mối quan hệ xảy ra-trước..)

Trả lời

12

Thay thế tham chiếu là an toàn. Xem Java language Specification:

Khi một chủ đề sử dụng giá trị của biến, giá trị mà nó nhận được thực tế là một giá trị được lưu vào biến đó theo chuỗi đó hoặc bởi một chuỗi khác. Điều này đúng ngay cả khi chương trình không chứa mã để đồng bộ hóa thích hợp. Ví dụ, nếu hai luồng lưu trữ các tham chiếu đến các đối tượng khác nhau vào cùng một giá trị tham chiếu, biến này sau đó sẽ chứa một tham chiếu đến một đối tượng hoặc một đối tượng khác, không tham chiếu đến một đối tượng khác hoặc giá trị tham chiếu bị hỏng. (Có một ngoại lệ đặc biệt cho các giá trị lâu dài và đôi, xem §17.4.)

+3

@unknown: văn bản được trích dẫn không nói những gì bạn nghĩ nó nói !! Trong thực tế, viên đạn tiếp theo trong JLS nói điều này: "Trong trường hợp không đồng bộ hóa rõ ràng, việc thực hiện là miễn phí để cập nhật bộ nhớ chính theo thứ tự có thể gây ngạc nhiên. Do đó, lập trình viên muốn tránh những điều bất ngờ nên sử dụng đồng bộ hóa rõ ràng. " –

+1

@unknown: lý do duy nhất mà mã của OP là an toàn là anh ta đã khai báo biến là 'volatile'. –

+3

@Stephen Tôi nghĩ điểm chính của câu hỏi là về nguyên tử của nhiệm vụ. Đó là lý do tại sao tôi trích dẫn phần này của spec. Nếu tôi hiểu chính xác, thì nguyên tử này được đảm bảo ngay cả khi không dễ bay hơi. Tuy nhiên, điều đó có thể xảy ra, các chủ đề khác sẽ không bao giờ thấy cập nhật cho biến và tiếp tục thấy tham chiếu "cũ". Tuy nhiên một chuỗi sẽ không bao giờ thấy "một tham chiếu đến một số đối tượng khác hoặc một giá trị tham chiếu bị hỏng". – Wolfgang

0

ConcurrentHashMp là:

Bảng băm hỗ trợ đồng thời đầy đủ các lần truy lục và điều chỉnh đồng thời dự kiến ​​cho các bản cập nhật. Lớp này tuân theo cùng một đặc tả chức năng như Hashtable, và bao gồm các phiên bản của các phương thức tương ứng với từng phương thức của Hashtable. Tuy nhiên, mặc dù tất cả các thao tác đều an toàn với luồng, các hoạt động truy xuất không yêu cầu khóa và không có bất kỳ hỗ trợ nào để khóa toàn bộ bảng theo cách ngăn chặn tất cả truy cập. Lớp này hoàn toàn tương thích với Hashtable trong các chương trình dựa vào sự an toàn của luồng nhưng không dựa trên các chi tiết đồng bộ hóa của nó.

javadocs nói rằng đó là chủ đề an toàn.

Dường như có nhiều chu kỳ công việc và CPU để đặt cấu hình. Nó thực sự là động lực này? Hay bạn thay đổi mỗi tháng một lần và chỉ cần một dịch vụ bị trả lại khi bạn làm vậy?

+0

Cảm ơn câu trả lời của bạn! Tôi đã cố gắng làm cho câu hỏi của mình rõ ràng hơn và chỉnh sửa câu hỏi của tôi. –

0

Nếu bằng cách cập nhật bạn có nghĩa là ghi đè lên một mục bên trong ConcurrentHashMap:

FooBar.myConfigData.put(somekey, somevalue); 

Sau đó, nó chắc chắn là chủ đề an toàn, như duffymo nói.

Nếu bạn muốn ghi đè lên các biến myConfigData với một giá trị mới:

FooBar.myConfigData = new ConcurrentHashMap(); 

Nó cũng là thread-an toàn, sau khi bạn đã dán nhãn chính xác các biến như dễ bay hơi. Từ khóa volatile có nghĩa là nhiều luồng có thể truy cập cùng một biến một cách an toàn và nguyên tử.

CHỈNH SỬA: Câu hỏi không đồng bộ ConcurrentHashMap là chủ đề an toàn (theo javadoc) mà đúng hơn là Thiết lập Bản đồ ConcurrentHashMap trong biến Thành viên myConfigData. Biến này có thể được đọc và viết "cùng một lúc" bởi một số luồng nên câu hỏi là, nếu cài đặt là nguyên tử hay không. Tôi nghĩ rằng điều này có thể được khái quát hóa, là thiết lập của một biến tham chiếu Java nguyên tử hay không.

(Tôi cũng làm cho nó dễ bay hơi. Đây là vấn đề khác và không liên quan gì đến nguyên tử (câu hỏi của tôi) mà là "khả năng hiển thị trong các chủ đề khác" và điều xảy ra trước mối quan hệ).

Thực tế 'dễ bay hơi' cho nguyên tử, không có gì ảnh hưởng đến khả năng hiển thị, biến công khai sẽ luôn hiển thị với mọi chuỗi.

+0

Cảm ơn bạn cũng rất nhiều cho câu trả lời của bạn! –

2

volatile đảm bảo nguyên tử, khả năng hiển thị và hoạt động như một 'rào cản bộ nhớ' (google, nếu bạn muốn biết điều đó có nghĩa là gì) - ít nhất là từ Java 5. Do đó nó thực hiện chính xác những gì bạn muốn.

0

Bạn có thể sử dụng AtomicReference nếu bạn cảm thấy không chắc chắn.

Mặc dù tôi nghĩ rằng trong trường hợp của bạn dễ bay hơi là đủ.

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