2009-10-12 42 views
6

Tôi đã sử dụng hàng đợi chung trong bộ sưu tập C# và mọi người đều nói rằng tốt hơn là nên sử dụng đối tượng System.Collection.Generic.Queue vì sự an toàn của luồng.Đối tượng 'an toàn chủ đề' có nghĩa là gì?

Vui lòng thông báo cho đúng quyết định sử dụng đối tượng Queue và làm thế nào nó là an toàn?

Trả lời

5

Loại an toàn chủ đề có thể được truy cập an toàn từ nhiều luồng mà không cần quan tâm đến đồng thời. Điều này thường có nghĩa là loại đó là chỉ đọc.

Điều thú vị đủ, Queue<T> là an toàn không dây.

Để suy nghĩ về an toàn luồng, hãy xem xét điều gì sẽ xảy ra nếu hai luồng truy cập Queue<T> và chuỗi thứ ba xuất hiện và bắt đầu thêm hoặc xóa khỏi số Queue<T> này. Vì loại này không hạn chế hành vi này, nó không phải là luồng an toàn.

25

"Chủ đề an toàn" là một phần của thuật ngữ không may vì nó không thực sự có định nghĩa vững chắc. Về cơ bản nó có nghĩa là một số hoạt động trên đối tượng được đảm bảo hoạt động hợp lý khi đối tượng đang được vận hành trên nhiều luồng.

Hãy xem xét ví dụ đơn giản nhất: bộ đếm. Giả sử bạn có hai luồng đang tăng bộ đếm. Nếu chuỗi sự kiện diễn ra:

  • Chủ đề đọc từ quầy, được không.
  • Chủ đề hai lần đọc từ bộ đếm, được không.
  • Tạo một số không, viết một lượt truy cập.
  • Thêm hai số không, viết một lượt truy cập.

Sau đó, hãy lưu ý cách bộ đếm đã "mất" một trong các số gia. Hoạt động gia tăng đơn giản trên các quầy không phải là luồng an toàn; để làm cho chúng an toàn, bạn có thể sử dụng khóa hoặc InterlockedIncrement.

Tương tự với hàng đợi. Các luồng không phải luồng-chủ đề có thể "mất" enqueues giống như cách mà các quầy không phải là luồng an toàn có thể mất các gia số. Tồi tệ hơn, không phải hàng đợi an toàn chủ đề thậm chí có thể sụp đổ hoặc tạo ra kết quả điên rồ nếu bạn sử dụng chúng trong một tình huống đa luồng không đúng cách.

Khó khăn với "chủ đề an toàn" là nó không được xác định rõ ràng. Liệu nó có nghĩa đơn giản là "sẽ không sụp đổ"? Điều đó có nghĩa là các kết quả hợp lý sẽ được tạo ra? Ví dụ: giả sử bạn có bộ sưu tập "chủ đề an toàn". Mã này có đúng không?

if (!collection.IsEmpty) Console.WriteLine(collection[0]); 

Không. Ngay cả khi bộ sưu tập là "chủ đề an toàn", điều đó không có nghĩa là mã này là chính xác; một chủ đề khác có thể đã làm cho bộ sưu tập trống sau khi kiểm tra nhưng trước khi các văn bản và do đó mã này có thể sụp đổ, ngay cả khi đối tượng được cho là "threadsafe". Trên thực tế xác định rằng mọi kết hợp có liên quan hoạt động là luồng an toàn là một vấn đề vô cùng khó khăn.

Bây giờ, hãy đến với tình huống thực tế của bạn: bất cứ ai nói với bạn "bạn nên sử dụng lớp Queue, tốt hơn vì nó là chủ đề an toàn" có lẽ không có ý tưởng rõ ràng về những gì họ đang nói. Trước hết, Hàng đợi không phải là chủ đề an toàn. Thứ hai, cho dù Queue là threadafe hay không là hoàn toàn không liên quan nếu bạn chỉ sử dụng các đối tượng trên một thread duy nhất! Nếu bạn có một bộ sưu tập sẽ được truy cập trên nhiều luồng, thì như tôi đã chỉ ra trong ví dụ trên, bạn có một vấn đề cực kỳ khó giải quyết, bất kể bản thân bộ sưu tập có phải là "threadsafe" hay không. Bạn phải xác định rằng mọi kết hợp hoạt động bạn thực hiện trên bộ sưu tập cũng là an toàn. Đây là một vấn đề rất khó khăn, và nếu nó là một trong những bạn phải đối mặt, sau đó bạn nên sử dụng các dịch vụ của một chuyên gia về chủ đề khó khăn này.

+5

+1 Đối với lời khai chuyên gia vững chắc. Bạn cũng đúng để chỉ ra rằng "thread an toàn" là một khái niệm khá mờ. –

+1

Tôi thích cách mọi câu hỏi liên quan đến chuỗi an toàn được trả lời bởi cùng một anh chàng, mà tôi đã đọc từ khoảng 2 giờ. –

1

Khi xử lý đa luồng, bạn thường phải đối phó với các vấn đề tương tranh. Thuật ngữ "vấn đề tương tranh" đề cập đến các vấn đề được giới thiệu cụ thể bởi khả năng xen kẽ các hướng dẫn từ hai bối cảnh thực thi khác nhau trên một tài nguyên được chia sẻ bởi cả hai. Ở đây, về an toàn luồng, ngữ cảnh thực hiện là hai luồng trong một tiến trình; tuy nhiên, trong các chủ đề liên quan, chúng có thể là các quá trình.

Các biện pháp an toàn chủ đề được đưa ra để đạt được hai mục tiêu chủ yếu. Đầu tiên là lấy lại quyết định liên quan đến điều gì sẽ xảy ra nếu luồng ngữ cảnh-chuyển đổi (được điều khiển bằng hệ điều hành khác và do đó về cơ bản không xác định trong các chương trình ở mức người dùng), để ngăn một số tác vụ bị bỏ lại một nửa hoặc hai ngữ cảnh cùng một vị trí trong bộ nhớ cái khác. Hầu hết các biện pháp chỉ cần sử dụng một chút các hướng dẫn test-and-set được hỗ trợ bởi phần cứng và mức độ tương tự, cũng như mức phần mềm synchronization constructs để buộc tất cả các ngữ cảnh thực thi khác tránh xa loại dữ liệu trong khi một số khác đang thực hiện công việc không nên bị gián đoạn.

Thông thường, các đối tượng chỉ đọc là an toàn chỉ. Nhiều đối tượng không đọc chỉ có thể truy cập dữ liệu (chỉ đọc) xảy ra với nhiều luồng không có vấn đề, nếu đối tượng không được sửa đổi ở giữa. Nhưng đây không phải là vấn đề an toàn. An toàn chủ đề là khi tất cả các cách thức của mọi thứ được thực hiện cho một kiểu dữ liệu để ngăn chặn bất kỳ sửa đổi nó bởi một sợi từ gây ra tham nhũng dữ liệu hoặc bế tắc ngay cả khi giao dịch với nhiều lần đọc và ghi đồng thời.

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