2010-06-30 21 views
13

Hey all, Tôi đang làm việc trên một số mã tôi thừa hưởng, có vẻ như một sợi được thiết lập một biến thành viên boolean trong khi thread khác trong một vòng lặp while kiểm tra nó. Điều này thực sự làm việc OK hay tôi nên thay đổi nó để sử dụng đồng bộ getters hoặc setters trên boolean var?Cần đồng bộ hóa cài đặt của các thành viên boolean?

+0

Câu trả lời hay cho đến nay các bạn, tôi đã nghĩ rằng vòng lặp while có thể là bộ nhớ đệm biến mà nó đang cố gắng kiểm tra cục bộ. Tôi đang thêm volatile bây giờ và đặt biến trong một getter đồng bộ và setter. –

+3

Tôi nghĩ rằng bạn đã không đọc các câu trả lời (và tài liệu) đúng cách, đặc biệt là một từ Tom Hawtin. Đồng bộ hóa truy cập vào một biến dễ bay hơi là một oxymoron. –

+0

Tôi đồng ý dễ bay hơi sẽ bảo vệ biến boolean của bạn và chắc chắn rằng nó đang được cập nhật và đọc đúng cách, nhưng bạn cần phải nhìn vào bức tranh lớn và chắc chắn rằng đối tượng của bạn luôn ở trạng thái nhất quán. –

Trả lời

7

Trong trường hợp đọc và viết một nguyên thủy như bool hoặc int tuyên bố họ là dễ bay hơi sẽ rất nhiều. Khi một chủ đề đọc chủ đề khác sẽ hoàn thành việc viết. Biến sẽ không bao giờ ở trạng thái không hợp lệ.

Có thể công bằng khi nói rằng trên toàn bộ, từ khóa dễ bay hơi trong Java kém tài liệu, ít được hiểu và hiếm khi được sử dụng. Để làm cho vấn đề tồi tệ hơn, định nghĩa chính thức của nó thực sự thay đổi theo Java 5. Về cơ bản, biến động được sử dụng để chỉ ra rằng giá trị của biến sẽ được sửa đổi bởi các luồng khác nhau.

Khai báo một biến Java dễ bay hơi có nghĩa là:

  1. Giá trị của biến này sẽ không bao giờ được cache thread-địa phương: tất cả đọc và viết sẽ đi thẳng đến "bộ nhớ chính";
  2. Truy cập vào biến hoạt động như mặc dù nó được đính kèm trong khối đồng bộ , được đồng bộ hóa trên chính nó.

Chúng ta nói "hành vi như thể" trong điểm thứ hai, bởi vì để các lập trình viên ít nhất (và có lẽ trong hầu hết các trường JVM) không có đối tượng khóa thực tế có liên quan.

http://www.javamex.com/tutorials/synchronization_volatile.shtml

+0

'volatile' được xác định chính xác trong thông số JLS và JVM. Tuy nhiên, nó dường như được sử dụng thường xuyên hơn nhiều so với hậu quả được hiểu. –

+0

@Tom Hawtin - Người ta cần hiểu những hạn chế. Nó là một công cụ mạnh mẽ trong một số tình huống giới hạn. –

+1

Trong khi những gì bạn nói là đúng của boolean (và trong một số trường hợp int) nguyên thủy, hãy cẩn thận với int khi thực hiện các hoạt động như int ++. Trong khi điều này dường như là một hoạt động duy nhất, nó không thực sự và chỉ sử dụng dễ bay hơi trong một trường hợp như thế này là không đủ. –

2

Hầu như chắc chắn bạn sẽ cần phải thêm khóa ở mức cao hơn. Chỉ cần thêm synchronized xung quanh việc truy cập một lần vào các trường hiếm khi hữu ích. Các thao tác tổng hợp sẽ không an toàn chỉ khi các hoạt động thành phần độc lập với luồng an toàn.

Ví dụ: xem xét xóa nội dung của tài liệu an toàn chỉ. Tài liệu này cung cấp hai thao tác an toàn chủ đề có liên quan: xóa nội dung giữa hai chỉ mục và hoạt động chiều dài. Vì vậy, bạn có được chiều dài và xóa từ số không đến độ dài, phải không? Vâng, có một cuộc đua vì tài liệu có thể thay đổi độ dài giữa việc đọc độ dài và xóa nội dung. Không có cách nào để làm cho thread hoạt động an toàn cho các hoạt động. (Ví dụ lấy từ Swing Text.)

+0

+1 điểm tốt để thêm một số quan điểm để xem xét nhiều hơn chỉ là biến boolean. –

+0

Điểm của bạn được thực hiện tốt nhưng không có ngữ cảnh, dựa trên câu hỏi được hỏi, để giới thiệu đối số tổng hợp. Câu hỏi đặt ra là về vấn đề người đọc/người viết boolean. Showboating? – bjg

+0

@bjg Threading liên quan đến ngữ cảnh. Nó vốn không phải là địa phương. Tôi tin rằng có khả năng là vấn đề trong tay đi xa hơn một boolean. Chắc chắn nó sẽ không có ích cho ai đó mới đến khu vực để giải quyết một vấn đề đặc biệt với mã khó hiểu. –

-1

tôi sẽ đề nghị rằng boolean được khai báo biến động và đọc và viết truy cập được đồng bộ

+0

Điều đó nghe có vẻ bối rối. (Ngoài ra 'volatile' là đáng ngạc nhiên không hữu ích (excapt ở mức thấp) vì các hoạt động thường đòi hỏi nhiều hoạt động thành phần.) –

+0

@tackline Bạn có nghĩa là nó bị nhầm lẫn bởi vì nó là một vành đai và niềng răng tiếp cận? Nếu có, thì trong khi tôi hiểu mô hình lập trình Java có thể cho rằng dễ bay hơi thì tôi vẫn nghi ngờ về yêu cầu này đối với tất cả các triển khai JVM mà tôi có thể gặp phải khi chạy trên các môi trường muti-core. Trong mọi trường hợp - ngay cả khi hoang tưởng của tôi không bị phát hiện - dễ bay hơi thì thường không phải là một gợi ý đủ mạnh cho những người bảo trì rằng có điều gì đó quan trọng mà họ cần phải biết về mối quan hệ với boolean trong câu hỏi – bjg

+0

Bạn nên khai báo một biến 'volatile' hoặc sử dụng accessors' sync'. Làm cả hai chỉ cản trở hiệu suất và tăng thêm độ phức tạp. Và Tom nói đúng rằng việc sử dụng chính xác của dễ bay hơi chủ yếu được dành riêng bởi các chuyên gia java.concurrent. –

0

Nếu bạn sử dụng java 1.5+, Bạn nên sử dụng Condition đồng bộ hóa ban.

Nếu bạn theo liên kết, nó có ví dụ hay về cách sử dụng.

0

Nó không được bảo đảm để làm việc nếu đó là một boolean đơn giản, một trong những chủ đề không thể thấy boolean được cập nhật do mô hình ký ức về java, bạn có thể

Hãy nhớ rằng không có cách nào trong số này có thể "hoạt động" nếu luồng đọc boolean này phụ thuộc vào giá trị trước đó của boolean - nó có thể bỏ lỡ các thay đổi đối với boolean đó, ví dụ:

thread1:

while(foo.myVolatileBoolean) { 
... 
} 

thread2:

foo.myVolatileBoolean = false; //thread 1 might never catch thisone. 
... 
foo.myVolatileBoolean = true; 

Nếu đây là một vấn đề và bạn cần phải theo dõi thay đổi đối với boolean, xem xét sử dụng wait()/thông báo() hoặc Condition

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