2010-11-01 24 views

Trả lời

12

Hãy tưởng tượng một thể hiện của một lớp có biến toàn cầu trong đó. Hãy tưởng tượng hai chủ đề gọi một phương thức trên đối tượng đó tại cùng một thời điểm và phương thức đó sẽ cập nhật biến toàn cầu bên trong.

Khả năng là giá trị trong biến sẽ bị hỏng. Các ngôn ngữ và trình biên dịch/thông dịch viên khác nhau sẽ giải quyết vấn đề này theo nhiều cách khác nhau (hoặc hoàn toàn không ...) nhưng vấn đề là bạn nhận được kết quả "không mong muốn" và "không thể đoán trước".

Bây giờ, hãy tưởng tượng rằng phương thức có được một "khóa" trên biến trước khi cố gắng đọc hoặc ghi vào nó. Chủ đề đầu tiên để gọi phương thức sẽ nhận được một "khóa" trên biến, chuỗi thứ hai để gọi phương thức sẽ phải chờ cho đến khi khóa được giải phóng bởi luồng đầu tiên. Mặc dù bạn vẫn có điều kiện chủng tộc (nghĩa là chuỗi thứ hai có thể ghi đè giá trị từ lần đầu tiên) ít nhất bạn có kết quả dự đoán được vì không có hai chuỗi (không biết lẫn nhau) có thể sửa đổi giá trị cùng một lúc.

Bạn sử dụng câu lệnh lock để nhận khóa đó trên biến. Thông thường bạn muốn định nghĩa một biến đối tượng riêng biệt và sử dụng cho đối tượng khóa:

public class MyThreadSafeClass 
{ 
    private readonly object lockObject = new object(); 
    private string mySharedString; 

    public void ThreadSafeMethod(string newValue) 
    { 
     lock (lockObject) 
     { 
      // Once one thread has got inside this lock statement, any others will have to wait outside for their turn... 
      mySharedString = newValue; 
     } 
    } 
} 

Một loại được coi là "thread-safe" nếu nó được áp dụng theo nguyên tắc không có hư hỏng sẽ xảy ra nếu chia sẻ dữ liệu được truy cập bởi nhiều chủ đề cùng một lúc.

Hãy coi chừng sự khác biệt giữa "không thay đổi" và "an toàn chỉ". Thread-safe nói rằng bạn đã mã hóa kịch bản và sẽ không bị hỏng nếu hai luồng truy cập trạng thái chia sẻ cùng một lúc, trong khi bất biến đơn giản chỉ là bạn trả về một đối tượng mới thay vì sửa đổi nó. Các đối tượng không thể thay đổi được an toàn theo chủ đề, nhưng không phải tất cả các đối tượng an toàn chủ đề đều không thay đổi được.

+0

Vì vậy, nếu loại an toàn chỉ, nó sẽ thực hiện khóa bên trong và tôi không nên thực hiện lại. Có đúng không? Cảm ơn Neil. –

+0

Có - nếu bạn đang sử dụng lại loại của người khác (ví dụ: từ thư viện của bên thứ ba) và được quảng cáo là "an toàn chủ đề", bạn không cần viết 'khóa (...) {... } 'phát biểu xung quanh tập quán của nó. Tuy nhiên, nếu bạn đang thiết lập một biến kiểu đó và biến tự nó có thể được sửa đổi bởi các luồng khác nhau, bạn cần phải khóa nó. –

7

Chủ đề đang an toàn có nghĩa là mã có thể được truy cập với nhiều chủ đề và vẫn hoạt động một cách chính xác.

Trong C#, điều này thường đòi hỏi một số loại cơ chế đồng bộ hóa. Một câu lệnh đơn giản là câu lệnh lock (phía sau hậu trường, gọi tới số Monitor.Enter). Một khối mã được bao quanh bởi một khối lock chỉ có thể được truy cập bởi một luồng tại một thời điểm.

Bất kỳ việc sử dụng loại nào không an toàn chỉ yêu cầu bạn phải tự quản lý đồng bộ hóa.


Tài nguyên tốt để tìm hiểu về luồng trong C# là sách điện tử miễn phí của Joe Albahari, được tìm thấy here.

+0

Cảm ơn bạn Oded đó là một tuyệt vời đọc và tôi rất khuyên bạn nên nó quá. –

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