2013-06-15 26 views
7

Vì vậy, đây là tiện ích tùy chỉnh của tôi cho khóa đã kiểm tra kép: đó là phương pháp tĩnh mà bạn cung cấp tiêu chí, đối tượng đồng bộ hóa và hành động được thực hiện.Có thể tạo một thử nghiệm cho thấy sự thất bại của việc kiểm tra khóa kép trong C# không?

public static bool RunIf(Func<bool> criterion, object syncObject, Action action) 
{ 
    if (criterion()) 
     lock(syncObject) 
      if (criterion()) 
      { 
       Thread.MemoryBarrier(); 
       action(); 
       return true; 
      } 
    return false; 
} 

Tôi trao cho hiểu rằng, theo C# đặc điểm kỹ thuật, nó có thể cho optimisers để sắp xếp lại cấp phát bộ nhớ theo cách như vậy đó, mà không có rào cản bộ nhớ, kỹ thuật này có thể cung cấp cho một dương tính giả và thực hiện hành động khi nó không nên. Trong thế giới nhỏ bé của tôi, nếu thất bại như vậy là có thể, nó cũng nên có thể đưa ra một thử nghiệm cho thấy sự thất bại một cách nhất quán bằng cách nhấn kịch bản đủ cứng với một số lượng đủ các trường hợp thử nghiệm song song. Tôi đã tìm kiếm một thử nghiệm như vậy trong khoảng một năm nay, nhưng cho đến nay tôi đã rút ra một khoảng trống. Bất kỳ ai có thể chỉ cho tôi một bài kiểm tra rằng:

  1. cho thấy sự thất bại của phương pháp này khi không có hàng rào bộ nhớ;

  2. cho thấy thành công của nó khi thử nghiệm được lặp lại với hàng rào bộ nhớ được khôi phục?

+3

Tôi tin rằng .Net framework trên x86 có mô hình bộ nhớ mạnh hơn những gì đặc tả C# yêu cầu, vì vậy bạn sẽ không thể tạo thử nghiệm như vậy. Bạn có thể có nhiều may mắn hơn trên ARM (ví dụ: Windows RT), có mô hình bộ nhớ yếu hơn. – svick

+3

svick là chính xác. Kiểm tra [bài viết MSDN này] (http://msdn.microsoft.com/en-us/magazine/cc163715.aspx#S5) nói về mô hình bộ nhớ mạnh hơn cho .Net 2+. –

Trả lời

1

Không, không thể kiểm tra hành vi không xác định (hoặc ít nhất, nếu bạn làm vậy thì kết quả âm tính vẫn chưa kết luận).

+0

Đồng ý, người ta có thể đưa ra một bài kiểm tra để có được hai chủ đề để gọi phương thức. Tuy nhiên, bạn không thể chuyển đổi giữa hai luồng. Tuy nhiên, mô hình được thực hiện, được biết đến và việc xem xét mã đơn giản nên được thực hiện. –

+0

Điều này đặt ra một câu hỏi khác. Bạn thực sự có thể bỏ khóa hoàn toàn kiểm tra đôi, và thực hiện một mẫu đơn giản không an toàn đơn giản có đầu óc. Mặc dù không có gì đảm bảo rằng điều này sẽ thất bại khi bị tấn công bởi các luồng song song - điều này, như bạn nói, hành vi không xác định - nếu bạn nhấn nó với một vài chủ đề song song, cơ hội nó sẽ thất bại nó là một thử nghiệm xác định một cách hiệu quả. Đó có phải là thực hành xấu? –

0

Không thể xây dựng một thử nghiệm như vậy, bởi vì tuyên bố "khóa" đã tạo ra một hàng rào đầy đủ (nghĩa là hàng rào phát hành và giải phóng) cho khối lệnh được khóa. Do đó, Thread.MemoryBarrier() bổ sung là không cần thiết và không có hiệu lực.

Vì vậy, tùy thuộc vào những gì được chuyển giao trong đại biểu criterion, cấu trúc RunIf của bạn an toàn hoặc hoàn toàn không cần thiết.

Điều tôi ngụ ý là, nếu giá trị trả về trong giá trị trả về từ trạng thái có thể thay đổi và trạng thái có thể thay đổi này không được bảo vệ (trực tiếp hoặc gián tiếp) bởi cùng syncObject, mã này không an toàn RunIf về cơ bản không có tác dụng gì ngoại trừ xung quanh các hướng dẫn được thực hiện trong cuộc gọi thứ hai tới đại diện criterion với một hàng rào đầy đủ.

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