2009-10-06 20 views
31

Tôi có một lớp có trạng thái (một enum đơn giản) và được truy cập từ hai luồng. Để thay đổi trạng thái, tôi sử dụng một mutex (boost :: mutex). Có an toàn để kiểm tra trạng thái (ví dụ: so sánh state_ == ESTABLISHED) hoặc tôi có phải sử dụng mutex trong trường hợp này không? Nói cách khác, tôi cần mutex khi tôi chỉ muốn đọc một biến mà có thể được đồng thời được viết bởi một thread?Tôi có cần một mutex để đọc không?

Trả lời

3

Có. Nếu chủ đề đọc một biến trong khi luồng b đang ghi vào nó, bạn có thể đọc một giá trị không xác định. Thao tác đọc và ghi không phải là nguyên tử, đặc biệt là trên một hệ thống đa bộ xử lý.

+0

trong khi chuỗi ghi (fetch-> write-> store) Tôi không thấy khi nào ở giữa những người đọc sẽ tìm nạp giá trị không xác định, hoặc giá trị trước đó, nhưng không bao giờ được xác định. –

+0

Tính các giá trị enum tài khoản được đọc trong một hướng dẫn. –

+1

@Arkaitz: không xác định có lẽ không phải là từ đúng. Nhưng các kiến ​​trúc CPU/bộ nhớ ngày càng trở nên phức tạp với các mức cache bổ sung, độ trễ tăng lên vv Câu trả lời rất đơn giản: Nói Không! để chia sẻ dữ liệu không bị khóa. Ngay cả các chuyên gia cũng phạm nhiều sai lầm trong lĩnh vực này. – sellibitze

0

Nói chung bạn không, nếu biến của bạn được khai báo là "dễ bay hơi". Và CHỈ nếu nó là một biến duy nhất - nếu không bạn nên thực sự cẩn thận về các chủng tộc có thể.

+0

Tại sao bạn nghĩ các vấn đề dễ bay hơi? – jalf

+1

@jalf: volatile yêu cầu trình biên dịch không thực hiện tối ưu hóa có thể làm cho mã của bạn nhìn thấy một bản sao cũ của biến. –

+2

Nhưng câu hỏi không phải là về các bản sao cũ. Ngay cả khi biến không phải là biến động, nó sẽ được viết ra sớm hay muộn. Nó sẽ là nguyên tử bất kể biến động, và dễ bay hơi không ngăn cản tải/lưu trữ sắp xếp lại. Vì vậy, dễ bay hơi không thực sự mua cho bạn bất cứ điều gì trong trường hợp này. Nó không giải quyết được vấn đề cần giải quyết, và nó giải quyết một vấn đề đã được giải quyết. – jalf

0

Cần bảo vệ quyền truy cập vào enum (đọc hoặc ghi).

Một điều khác: Nếu tranh chấp chủ đề ít hơn và các chủ đề thuộc cùng một quá trình thì phần quan trọng sẽ tốt hơn mutex.

8

Bạn có hai chủ đề, họ trao đổi thông tin, có bạn cần một mutex và bạn cũng có thể cần phải chờ đợi có điều kiện.

Trong ví dụ của bạn (so sánh state_ == ESTABLISHED) cho biết luồng # 2 đang chờ thread # 1 để khởi tạo kết nối/trạng thái. Không có mutex hoặc điều kiện/sự kiện, luồng # 2 phải thăm dò trạng thái liên tục.

Chủ đề được sử dụng để tăng hiệu suất (hoặc cải thiện khả năng phản hồi), bỏ phiếu thường dẫn đến hiệu suất giảm, hoặc bằng cách tiêu thụ rất nhiều CPU hoặc bằng cách giới thiệu latencey do khoảng thời gian thăm dò ý kiến.

+0

+1 để đề xuất các biến có điều kiện. Từ những âm thanh của nó, anh ta có một sợi chỉ cần phản ứng với sự thay đổi trạng thái bởi một sự thay đổi khác. Nếu đó là trường hợp các biến điều kiện thì thích hợp hơn nhiều. – Falaina

+0

@Ermelli chúng ta vẫn cần mutex nếu chúng ta muốn sử dụng vòng lặp chờ đợi bận rộn (vì vòng lặp có thể làm điều gì đó khác) – Nick

0

thực sự, không có lý do gì để khóa truy cập đối tượng để đọc. bạn chỉ muốn khóa nó khi viết cho nó. điều này chính là điều mà một khóa người đọc viết là. nó không khóa đối tượng miễn là không có hoạt động ghi. nó cải thiện hiệu suất và ngăn ngừa deadlocks. xem các liên kết sau đây để giải thích phức tạp hơn:

wikipedia codeproject

12

Nó phụ thuộc.

Ngôn ngữ C++ không nói gì về chủ đề hoặc nguyên tử.

Nhưng trên nhất CPU hiện đại, đọc số nguyên là hoạt động nguyên tử, có nghĩa là bạn sẽ luôn đọc giá trị nhất quán, ngay cả khi không có mutex.

Tuy nhiên, không có mutex hoặc một số hình thức đồng bộ hóa khác, trình biên dịch và CPU được tự do sắp xếp lại lần đọc và viết, vẫn không an toàn trong trường hợp chung.

Giả sử chuỗi nhà văn cập nhật một số dữ liệu, sau đó đặt cờ nguyên để thông báo cho các luồng khác có dữ liệu, có thể sắp xếp lại để cờ được đặt trước khi cập nhật dữ liệu. Trừ khi bạn sử dụng mutex hoặc một hình thức rào cản bộ nhớ khác.

Vì vậy, nếu bạn muốn hành vi chính xác, bạn không cần một mutex như vậy, và nó không có vấn đề nếu một thread ghi vào biến trong khi bạn đang đọc nó. Nó sẽ là nguyên tử trừ khi bạn đang làm việc trên một CPU rất bất thường.Nhưng bạn do cần một rào cản bộ nhớ của một số loại để ngăn chặn sắp xếp lại trong trình biên dịch hoặc CPU.

+0

Trừ khi bạn chỉ định biến động đọc (hoặc ghi) có thể * không bao giờ * được thực hiện. Sớm hay muộn thì không đủ tốt. – EFraim

+3

Nhưng ngay cả với biến động, CPU hoặc trình biên dịch có thể sắp xếp lại các bài viết, làm cho chúng vô nghĩa. Giải pháp chính xác là một rào cản bộ nhớ, và sau đó dễ bay hơi chỉ là một sự mất quyền lực không cần thiết. – jalf

+0

@ jalf: Không, nếu bạn chỉ cần một lá cờ duy nhất. Đọc lại câu hỏi. – EFraim

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