2012-03-30 29 views
16

Gần đây tôi đã thấy mã này trong một trang web, và câu hỏi của tôi là như sau:Khóa một biến bool đơn khi đa luồng?

 private bool mbTestFinished = false; 

     private bool IsFinished() 
     { 
      lock(mLock) 
      { 
       return mbTestFinished; 
      } 
     } 

     internal void SetFinished() 
     { 
      lock(mLock) 
      { 
       mbTestFinished = true; 
      } 
     } 

Trong một môi trường đa luồng, là thực sự cần thiết để khóa truy cập vào các mbTestFinished?

+6

Đây là cơ chế đáng tin cậy nhất để đảm bảo nó không phải là đọc CPU được lưu trữ (sẽ không hoạt động tốt giữa các luồng) - 'volatile' cũng sẽ hoạt động, nhưng vì lý do quá phức tạp (đây không phải là * intent * của 'volatile', nhưng đúng hơn là: tác dụng phụ) –

+4

@MarcGravell Tôi đã luôn luôn nghĩ rằng _was_ ý định của 'biến động'; bất kỳ cơ hội bạn có thể thả một liên kết tốt giải thích những gì là? –

+1

@romkyns: [answer] (http://stackoverflow.com/a/4103879/158779) cung cấp một số thông tin chi tiết. –

Trả lời

9

Có, nó là cần thiết. .Net môi trường sử dụng một số tối ưu hóa, và đôi khi nếu một vị trí bộ nhớ được truy cập thường xuyên, dữ liệu được chuyển vào thanh ghi CPU. Vì vậy, trong trường hợp này, nếu mbTestFinished là trong một thanh ghi CPU, sau đó một thread đọc nó có thể nhận được một giá trị sai. Vì vậy, bằng cách sử dụng phím dễ bay hơi đảm bảo, tất cả các truy cập vào biến này được thực hiện tại vị trí bộ nhớ, không phải tại các thanh ghi. Mặt khác, tôi không biết tần suất xảy ra này. Điều này có thể xảy ra ở tần số rất thấp.

9

Theo tôi, không, khóa là không cần thiết ở đây, vì hai lý do:

  1. biến Boolean không thể gây phân công rách như long ví dụ, do đó khóa là không cần thiết.
  2. Để giải quyết sự cố hiển thị volatile là đủ. Đúng là số lock giới thiệu một hàng rào ngầm, nhưng vì không cần đến lock cho nguyên tử, volatile là đủ.
+0

Điều này đúng với giả định mã được hiển thị là điều * duy nhất * sử dụng khóa. Nếu có những nơi khác mà 'mLock' được thực hiện, sự chuyển đổi thành 'biến động' có thể phá vỡ mọi thứ. –

+0

@romkyns: Vâng, tôi cho rằng đó là một kịch bản độc lập. – Tudor

4

Nếu mLock là CHỈ cho biến mbTestFinished, thì đó là một chút quá mức cần thiết. Thay vào đó, bạn có thể sử dụng dễ bay hơi hoặc Lồng vào nhau, vì cả hai đều là Cấu trúc chế độ người dùng để đồng bộ hóa luồng. khóa (hoặc Monitor) là một lai Xây dựng, theo nghĩa là nó cũng được tối ưu hóa để tránh quá cảnh từ/đến Kernel-Mode bất cứ khi nào có thể. Cuốn sách "CLR qua C#" có một cuộc thảo luận chuyên sâu về các khái niệm này.

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