2011-06-29 40 views
6

Kể từ Java 5, từ khóa volatile đã phát hành/có được ngữ nghĩa để hiển thị các hiệu ứng phụ cho các chủ đề khác (bao gồm các bài tập cho biến động không biến đổi!). Thực hiện hai biến này, ví dụ:dễ bay hơi với phát hành/có được ngữ nghĩa

int i; 
volatile int v; 

Lưu ý rằng i là biến không thường xuyên, không bay hơi. Hãy tưởng tượng thread 1 thực hiện những điều khoản sau đây:

i = 42; 
v = 0; 

Tại một số điểm sau trong thời gian, chủ đề 2 thực hiện những điều khoản sau đây:

int some_local_variable = v; 
print(i); 

Theo mô hình bộ nhớ Java, ghi của v trong chủ đề 1 tiếp theo là đọc của v trong chủ đề 2 đảm bảo rằng thread 2 thấy ghi vào i được thực thi trong chuỗi 1, vì vậy giá trị 42 được in.

Câu hỏi của tôi là: volatile có cùng bản phát hành/có được ngữ nghĩa trong C# không?

+1

Không chính xác; xem http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different-part-three.aspx –

Trả lời

14

Ngữ nghĩa của "dễ bay hơi" trong C# được xác định trong phần 3.10 và 10.4.3 của đặc điểm kỹ thuật. Thay vì sao chép chúng ở đây, tôi khuyến khích bạn tìm kiếm nó trong spec, và sau đó quyết định rằng nó quá phức tạp và nguy hiểm để sử dụng "dễ bay hơi", và quay lại sử dụng khóa.Đó là những gì tôi luôn làm.

Xem thông số 3.10 Execution Order10.4.3 Volatile Fields.

+0

Cố gắng né tránh các lập trình viên C++ từ các chi tiết "phức tạp và nguy hiểm" có lẽ sẽ có hiệu ứng ngược lại;) – fredoverflow

+0

@Fred Vì vậy, bạn chỉ quan tâm đến sự biến động vì nó phức tạp và nguy hiểm? –

+1

@ David: Tôi chỉ đơn giản là không thích kiến ​​thức không chính xác, và ấn tượng của tôi là 'biến động' là một trong những từ khóa bị hiểu lầm nhiều nhất từ ​​trước tới nay. Tôi muốn biết làm thế nào công cụ công cụ, đó là tất cả :) – fredoverflow

6

Vâng, tôi tin rằng nó đảm bảo rằng nếusome_local_variable được đọc như 0 (do ghi vào v), i sẽ được đọc như 42.

Phần khôn lanh là "tại một số điểm sau này trong thời gian ". Trong khi thường biến động được nói về mặt "đỏ bừng" viết, đó không phải là cách nó thực sự được định nghĩa trong spec (Java hoặc C#).

Từ ngôn ngữ đặc tả C# 4, phần 10.5.3:

Đối với các trường non-volatile, kỹ thuật tối ưu hóa mà sắp xếp lại các hướng dẫn có thể dẫn đến kết quả bất ngờ và không thể đoán trước trong các chương trình đa luồng truy cập vào các lĩnh vực mà không cần đồng bộ hóa như được cung cấp bởi tuyên bố khóa (§8.12). Những tối ưu hóa này có thể được thực hiện bởi trình biên dịch, bởi hệ thống thời gian chạy, hoặc bằng phần cứng. Đối với các trường dễ bay hơi, việc tối ưu hóa sắp xếp lại bị hạn chế:

  • Đọc của trường dễ bay hơi được gọi là đọc dễ bay hơi. Một đọc dễ bay hơi có "có được ngữ nghĩa"; có nghĩa là, nó được đảm bảo xảy ra trước khi bất kỳ tham chiếu đến bộ nhớ xảy ra sau khi nó trong trình tự lệnh.
  • Ghi một trường dễ bay hơi được gọi là ghi dễ bay hơi. Một ghi dễ bay hơi có "phát hành ngữ nghĩa"; có nghĩa là, nó được đảm bảo xảy ra sau bất kỳ tham chiếu bộ nhớ nào trước khi lệnh viết trong chuỗi lệnh.

Có thì một ví dụ đó là khá giống như của bạn, nhưng có điều kiện về giá trị đọc từ biến dễ bay hơi.

Và giống như Eric, tôi mạnh mẽ tránh dựa vào bản thân dễ bay hơi. Thật khó để giải thích, và tốt nhất là rời khỏi Joe Duffy/Stephen Toubs của thế giới.

+0

Bạn có thể cụ thể hơn với ý nghĩa của mình không liên quan đến "xả" viết bằng Java? Bạn có ngụ ý rằng mã của tôi thậm chí không hoạt động trong Java không? – fredoverflow

+0

@Fred Vâng nếu chúng tôi tin rằng trích dẫn nhỏ của Jon, có vẻ như C# đảm bảo ngữ nghĩa phát hành để viết và thu được ngữ nghĩa cho lần đọc, điều đó có nghĩa là có ví dụ sẽ hoạt động tốt trong cả java và C# .. và bây giờ bạn vẫn có đi và đọc các phần quan trọng để chắc chắn không bỏ lỡ một số trường hợp góc. Và trong khi tôi hoàn toàn có thể hiểu lý do tại sao tránh biến động (và semaphores và tất cả các thứ khác ở mức độ thấp) nói chung không có ý tưởng tồi, tôi cũng ghét có lỗ trong kiến ​​thức của tôi - và chỉ vì bạn biết cách sử dụng dễ bay hơi, không không có nghĩa là bạn phải! – Voo

+0

@Fred: Vấn đề là bạn chưa định nghĩa ý bạn là "một thời gian sau". Những gì bạn có thể đảm bảo là * if * thread 2 thấy ghi vào biến dễ bay hơi, sau đó nó sẽ * cũng * xem ghi vào biến không bay hơi. –

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