2008-12-28 33 views
8

Tôi có biến loại tham chiếu là readonly, vì tham chiếu không bao giờ thay đổi, chỉ các thuộc tính của nó. Khi tôi cố gắng thêm các sửa đổi volatile cho nó biên soạn cảnh báo tôi rằng nó sẽ không cho phép cả hai sửa đổi áp dụng cho cùng một biến. Nhưng tôi nghĩ tôi cần nó dễ bay hơi vì tôi không muốn có vấn đề về bộ nhớ đệm khi đọc các thuộc tính của nó. Tôi có thiếu gì không? Hoặc là trình biên dịch sai?Tại sao các công cụ sửa đổi chỉ đọc và dễ bay hơi được loại trừ lẫn nhau?

Cập nhật Như Martin đã nêu trong một trong các nhận xét dưới đây: Cả hai chỉ đọc và biến đổi dễ bay hơi chỉ áp dụng cho tham chiếu và không cho thuộc tính của đối tượng, trong trường hợp đối tượng kiểu tham chiếu. Đó là những gì tôi đã mất tích, do đó, trình biên dịch là đúng.

class C 
{ 
    readonly volatile string s; // error CS0678: 'C.s': a field cannot be both volatile and readonly 
} 
+0

Trình biên dịch là [có thể sai] (http://stackoverflow.com/q/39004125/1149773) (mặc dù có thể không dành cho trường hợp cụ thể của bạn). – Douglas

Trả lời

14

Cả các công cụ sửa đổi readonly cũng không phải volatile đều bị xâm nhập. Chúng áp dụng cho tham chiếu, chứ không áp dụng cho các thuộc tính của đối tượng.

Từ khóa readonly khẳng định — và thực thi — rằng biến số không thể thay đổi sau khi khởi tạo. Biến là bộ nhớ nhỏ, nơi tham chiếu được lưu trữ.

Từ khóa volatile cho trình biên dịch biết nội dung của biến có thể được thay đổi bởi nhiều chuỗi. Điều này ngăn cản trình biên dịch sử dụng tối ưu hóa (chẳng hạn như đọc giá trị của biến vào sổ đăng ký và sử dụng giá trị đó qua một số hướng dẫn) có thể gây ra sự cố khi truy cập đồng thời. Một lần nữa, điều này chỉ ảnh hưởng đến đoạn nhỏ của bộ nhớ, nơi tài liệu tham khảo được lưu trữ.

Được áp dụng theo cách này, bạn có thể thấy rằng chúng thực sự là loại trừ lẫn nhau. Nếu một cái gì đó là chỉ đọc (chỉ có thể được viết một lần, lúc khởi tạo hoặc xây dựng), thì nó cũng không thể dễ bay hơi (có thể được ghi vào bất kỳ lúc nào bằng nhiều luồng).


Vì lo ngại về các vấn đề bộ nhớ đệm, IIRC, có các quy tắc khá nghiêm ngặt về thời điểm trình biên dịch có thể lưu lại kết quả cuộc gọi thuộc tính. Hãy nhớ rằng nó một cuộc gọi phương thức và đó là một tối ưu hóa khá nặng (từ điểm của trình biên dịch) để lưu trữ giá trị của nó và bỏ qua gọi lại. Tôi không nghĩ rằng đó là điều bạn cần phải quan tâm chính mình với quá nhiều.

+1

Các thuộc tính có thể được uncacheable (tôi sẽ không biết), nhưng các lĩnh vực sao lưu chắc chắn là. Các trường cần được đánh dấu dễ bay hơi. – configurator

+0

Câu trả lời này giải quyết câu hỏi của OP một cách chính xác, nhưng nó chứa một tuyên bố gây hiểu lầm: "Từ khóa dễ bay hơi cho trình biên dịch biết nội dung của biến có thể được thay đổi bởi nhiều chuỗi." Đó chỉ là một phần chính xác; từ khóa dễ bay hơi cũng cho trình biên dịch biết rằng nội dung của một biến có thể được thay đổi * hoặc đọc * bởi nhiều luồng đồng thời, ngay cả khi thay đổi chỉ được thực hiện một lần. Tôi đã đặt ra một câu hỏi tương tự ở đây bao gồm vấn đề này: [C# ngôn ngữ lỗ hổng: dễ bay hơi và chỉ đọc không nên loại trừ lẫn nhau] (http://stackoverflow.com/q/39004125/1149773). – Douglas

+0

Tôi không nghĩ rằng tuyên bố của tôi là gây hiểu lầm. Có lẽ sẽ chính xác hơn khi nói rằng trình biên dịch nói rằng giá trị của biến có thể bị thay đổi bởi các luồng khác trong khi luồng đang đọc nó, nhưng tôi nghĩ * rằng * phrasing gây hiểu lầm hơn mà không giải thích thêm, vì nó có thể ngụ ý rằng 'volatile' là tất cả những gì cần thiết để cung cấp đồng bộ hóa luồng. Tôi nghĩ rằng từ ngữ của tôi giải thích khái niệm rõ ràng, và câu tiếp theo cung cấp đủ chi tiết cho một sự hiểu biết cơ bản. Vấn đề của bạn là một sự kiểm tra thú vị về hành vi khởi tạo của .NET, nhưng nó không làm giảm đi điều này. –

1

Trường chỉ đọc có thể được viết khi đối tượng được xây dựng lần đầu tiên. Do đó sẽ không có bất kỳ vấn đề bộ nhớ đệm nào trên CPU vì trường này là bất biến và không thể thay đổi.

+0

Tôi hiểu logic của bạn, nhưng tôi không đồng ý. Một đối tượng có thể được chỉ đọc và vẫn thay đổi thông qua các thuộc tính của nó, bởi vì các thuộc tính của nó không chỉ đọc. Thuộc tính chỉ đọc trong trường hợp này chỉ ngăn cản việc gán biến cho một đối tượng khác. Ít nhất là những gì tôi hiểu từ những gì tôi đã học được. –

+2

@Vernict: Các công cụ sửa đổi chỉ đọc và dễ bay hơi chỉ bảo vệ tham chiếu (hoặc giá trị trong trường hợp các giá trị nguyên tử như bool, int), không phải nội dung của đối tượng! Đó là một vấn đề hoàn toàn khác. –

0

Mặc dù bản thân tài liệu tham khảo có thể an toàn cho luồng nhưng các thuộc tính của nó có thể không. Hãy suy nghĩ về điều gì sẽ xảy ra nếu hai chuỗi cố gắng lặp lại đồng thời thông qua Danh sách chứa trong phạm vi đối tượng tham chiếu của bạn.

+0

Nhưng đó là một cái gì đó không chỉ đọc và cũng không dễ bay hơi được dự định để bảo vệ chống lại. Đó là một cái gì đó bạn cần phải giải quyết với anyways đồng bộ hóa. –

+0

@Charlie, bạn đang nói rằng ngay cả khi đối tượng là dễ bay hơi, nó không đảm bảo rằng các thuộc tính của nó sẽ dễ bay hơi? –

+0

@Martin C, rất đúng. @Vernicht, Như tôi đã hiểu, vâng. Bạn sẽ cần đảm bảo rằng các trường và thuộc tính của bạn an toàn chỉ. –

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