2010-01-11 2 views
11

Có cần thiết để bảo vệ quyền truy cập vào một biến duy nhất của loại tham chiếu trong ứng dụng đa luồng không? Tôi hiện đang khóa biến đó như sau:Khóa có cần thiết trong tình huống này không?

private readonly object _lock = new object(); 
private MyType _value; 
public MyType Value 
{ 
    get { lock (_lock) return _value; } 
    set { lock (_lock) _value = value; } 
} 

Nhưng tôi tự hỏi điều này có thực sự cần thiết không? Không được gán giá trị cho một trường nguyên tử? Bất cứ điều gì có thể đi sai nếu tôi không khóa trong trường hợp này?

P.S .: MyType là một lớp không thay đổi: tất cả các trường được đặt trong hàm tạo và không thay đổi. Để thay đổi một cái gì đó, một cá thể mới được tạo và gán cho biến trên.

+4

Giả sử tôi hỏi bạn "có phải là khóa trên cánh cửa cần thiết không?" Bạn cũng có thể đáp ứng bằng cách lưu ý rằng tôi đã không mô tả cánh cửa hoặc nhiệm vụ cánh cửa được thiết kế để thực hiện. Một khóa là cần thiết trên một cánh cửa nếu nhiệm vụ mà cánh cửa được phát minh ra để thực hiện không thể đạt được mà không cần thêm một khóa. Không ai có thể cho bạn biết công việc mà biến của bạn được thiết kế cho có thể đạt được mà không có khóa trừ khi bạn nói cho họ biết nhiệm vụ đó là gì. Đưa ra một giải thích * chi tiết và đầy đủ * của mọi kịch bản luồng có thể * mà biến có thể được sử dụng và ngữ nghĩa bạn muốn xảy ra trong mỗi ngữ cảnh. –

Trả lời

10

Làm nguyên tử hiếm khi đủ.

Tôi thường muốn có được giá trị mới nhất cho một biến, thay vì có khả năng nhìn thấy một biến cũ - vì vậy một số loại rào cản bộ nhớ là cần thiết, cho cả đọc và viết. Khóa là một cách đơn giản để có được quyền này, với chi phí có khả năng mất một số hiệu suất do tranh chấp.

I sử dụng để tin rằng biến biến động sẽ đủ trong tình huống này. Tôi không còn bị thuyết phục như vậy nữa. Về cơ bản tôi cố gắng tránh viết mã không khóa khi dữ liệu được chia sẻ có liên quan, trừ khi tôi có thể sử dụng các khối xây dựng được viết bởi những người thực sự hiểu những điều này (ví dụ: Joe Duffy).

+0

bạn r right. câu trả lời của tôi là không chính xác. – Benny

+1

Ngoài ra, như bản thân bạn nói trong http://www.yoda.arachsys.com/csharp/threads/volatility.shtml, thậm chí không có sự đảm bảo về việc gán là nguyên tử (phụ thuộc vào sự liên kết bộ nhớ) –

+1

@Jon, the " mới nhất vs cũ "là kinda nebulous và không dứt khoát. Tôi có nghĩa là ngay cả khi nó được khóa và bảo vệ đầy đủ, giá trị bạn nhận được với một đọc là không thỏa mãn về hành vi hơi ngẫu nhiên của thuật toán switchng quá trình OS ... Nó có thể chạy chuỗi đọc của bạn ngay trước ghi "đồng thời" khác, hoặc ngược lại ... Lớp vấn đề này nằm ngoài phạm vi của những gì chúng ta thường xem xét một vấn đề đa luồng. Nếu nó là quan trọng, nó cần phải được quản lý với một số cơ chế khác ... không? –

0

tất cả phụ thuộc vào việc thuộc tính có được truy cập bởi nhiều chuỗi hay không. và một số biến được gọi là hoạt động nguyên tử, trong trường hợp hoạt động nguyên tử này, không cần sử dụng khóa. xin lỗi vì tiếng anh nghèo.

trong trường hợp của bạn, không thay đổi, tôi nghĩ khóa là không cần thiết.

+2

Cho dù đối tượng là bất biến không có liên quan. Biến * có thể thay đổi; đó là lý do tại sao chúng được gọi là "biến". –

+0

-1 vì Eric đã đúng. – tony

7

Có từ khóa volatile cho điều này. Cho dù đó là an toàn mà không có nó phụ thuộc vào kịch bản. Nhưng trình biên dịch có thể thực hiện funny stuff, chẳng hạn như sắp xếp lại thứ tự hoạt động. Vì vậy, ngay cả đọc/ghi vào một trường có thể không an toàn.

+0

này, liên kết của bạn dễ bay hơi là không chính xác ... –

+0

Sai lầm của tôi. Đã sửa liên kết. – ewernli

+1

Tôi sẽ thêm, mặc dù: 'volatile' sẽ không khắc phục được sự cố trong mọi trường hợp. –

4

Nó có thể là một vấn đề. Nó không chỉ là nhiệm vụ mà bạn phải quan tâm. Do bộ đệm ẩn, các chuỗi đồng thời có thể thấy phiên bản cũ của đối tượng nếu bạn không khóa. Vì vậy, cho dù một khóa là cần thiết sẽ phụ thuộc vào chính xác cách bạn sử dụng nó, và bạn không hiển thị điều đó.

Đây là số free, sample chapter of "Concurrent Programming in Windows" giải thích chi tiết vấn đề này.

+0

Nó không phải là 'bộ nhớ đệm'. Nó sắp xếp lại các hướng dẫn trong bộ đệm đọc/ghi đang chờ xử lý. Tương tự nhưng không giống nhau. Các cache trong hầu hết các CPU đều mạch lạc. Đó là thứ tự các giá trị được ghi vào bộ nhớ cache đầu tiên. – tony

+0

Tony, bạn nói đúng là viết lại hướng dẫn có liên quan và sai bộ nhớ đệm không phải là. Với nhiều CPU, mỗi CPU có bộ nhớ cache của riêng mình, bộ nhớ này không được đảm bảo để nhất quán bên ngoài khóa. Xem, ví dụ: http://www.bluebytesoftware.com/blog/2009/10/20/FalseSharingIsNoFun.aspx –

+0

Xin lỗi; liên kết sai. Hãy thử http://www.bluebytesoftware.com/blog/2009/05/17/LoadsCannotPassOtherLoadsRevisited.aspx –