2010-08-30 41 views
15

Tại sao lớp java này không phải là Thread an toàn.An toàn chủ đề trong lớp Java

class TestClass { 
    private int x; 

    int get() { 
     return x; 
    } 

    void set(int x) { 
     this.x = x; 
    } 
} 

Tôi đọc từ khóa synchronized là cần thiết để làm cho chuỗi đó an toàn? Sau khi tất cả không phải là các hoạt động được thực hiện bên trong nguyên tử?

+1

riêng void int x? –

Trả lời

11

Mặc dù bản thân nhiệm vụ là một hoạt động nguyên tử, do phần cứng và trình biên dịch khác nhau triển khai, các luồng khác nhau có thể thấy các giá trị khác nhau của thành viên x. Tức là, một sửa đổi bởi một sợi có thể được ẩn với chủ đề khác, vì một số loại bộ nhớ đệm. Điều này thường được gọi là sự cố hiển thị chủ đề thread.

Bạn có thể đồng bộ hóa mã của mình đúng cách bằng cách đồng bộ hóa trên màn hình (sử dụng từ khóa được đồng bộ hóa hoặc khóa java.util.concurrent) hoặc bằng cách tuyên bố x là dễ bay hơi.

+0

Có giống như vậy trong C#? – devnull

8

Với nhiều bộ xử lý, một số giá trị có thể được bộ nhớ cache lưu vào bộ nhớ cache và có thể không phản ánh các thay đổi của các chủ đề/bộ xử lý khác cho cùng một đối tượng. Trên thực tế, JVM có thể được triển khai để hoạt động theo cách này ngay cả với một bộ xử lý đơn lẻ.

Các phương thức đồng bộ được yêu cầu rõ ràng theo đặc tả ngôn ngữ để trình bày rào cản bộ nhớ và yêu cầu đọc lại tất cả các biến mẫu từ bộ nhớ.

Vì mã của bạn không được đồng bộ hóa, một chuỗi có thể đặt giá trị, nhưng chuỗi khác sẽ trả về giá trị vẫn được lưu trong bộ nhớ cache theo chuỗi đó.

Vui lòng đọc 'Memory and Locks' chương của Đặc tả ngôn ngữ Java.

+1

Lý do cho downvote? –

5

Vì trường 'x' không được khai báo dễ bay hơi nên không có yêu cầu đối với JVM để đảm bảo rằng 'x' hiển thị cho tất cả các chuỗi khác. I E. nếu một luồng liên tục đọc giá trị của 'x' và một luồng khác đang viết nó, có thể là chuỗi đọc sẽ không bao giờ "thấy" thay đổi giá trị.

Một từ khóa đồng bộ là không cần thiết, nhưng sẽ hoạt động vì nó sẽ tạo ra rào cản bộ nhớ/bộ nhớ đệm cần thiết để đảm bảo 'x' hiển thị, nhưng sử dụng từ khóa dễ bay hơi trong trường hợp này sẽ hiệu quả hơn.

1

Khi bạn có hai phương pháp sửa đổi/truy cập biến không biến động, nó không bao giờ là chủ đề an toàn. Nếu bạn muốn chỉ có một phương pháp bạn có thể thử:

synchronized int getAndSet(int x, boolean set) { 
    if (set) this.x = x; 
    return this.x; // param x is for set 
} 
Các vấn đề liên quan