2010-06-07 44 views
5

Như tôi đã hiểu, mô hình bộ nhớ .NET trên máy 32 bit đảm bảo viết từ 32 bit và đọc là hoạt động nguyên tử nhưng không cung cấp đảm bảo này cho các từ 64 bit. Tôi đã viết một công cụ nhanh để chứng minh hiệu ứng này trên một hệ điều hành Windows XP 32-bit và đang nhận được kết quả phù hợp với mô tả bộ nhớ mô hình đó..NET 3.5SP1 Mô hình bộ nhớ 64 bit so với mô hình bộ nhớ 32 bit

Tuy nhiên, tôi đã thực hiện cùng công cụ này và chạy nó trên hệ điều hành Windows 7 Enterprise 64 bit và nhận được kết quả cực kỳ khác. Cả hai máy đều giống nhau chỉ với các hệ điều hành khác nhau được cài đặt. Tôi đã có thể mong đợi rằng các mô hình bộ nhớ .NET sẽ đảm bảo viết và đọc cho BOTH 32-bit và 64-bit từ được nguyên tử trên một hệ điều hành 64-bit. Tôi thấy kết quả hoàn toàn trái ngược với BOTH giả định. Đọc và ghi 32 bit không được chứng minh là nguyên tử trên hệ điều hành này.

Ai đó có thể giải thích cho tôi lý do tại sao điều này không thành công trên hệ điều hành 64 bit?

đang Tool:

using System; 
using System.Threading; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var th = new Thread(new ThreadStart(RunThread)); 
      var th2 = new Thread(new ThreadStart(RunThread)); 
      int lastRecordedInt = 0; 
      long lastRecordedLong = 0L; 
      th.Start(); 
      th2.Start(); 
      while (!done) 
      { 
       int newIntValue = intValue; 
       long newLongValue = longValue; 
       if (lastRecordedInt > newIntValue) Console.WriteLine("BING(int)! {0} > {1}, {2}", lastRecordedInt, newIntValue, (lastRecordedInt - newIntValue)); 
       if (lastRecordedLong > newLongValue) Console.WriteLine("BING(long)! {0} > {1}, {2}", lastRecordedLong, newLongValue, (lastRecordedLong - newLongValue)); 
       lastRecordedInt = newIntValue; 
       lastRecordedLong = newLongValue; 
      } 
      th.Join(); 
      th2.Join(); 
      Console.WriteLine("{0} =? {2}, {1} =? {3}", intValue, longValue, Int32.MaxValue/2, (long)Int32.MaxValue + (Int32.MaxValue/2)); 
     } 

     private static long longValue = Int32.MaxValue; 
     private static int intValue; 
     private static bool done = false; 

     static void RunThread() 
     { 
      for (int i = 0; i < Int32.MaxValue/4; ++i) 
      { 
       ++longValue; 
       ++intValue; 
      } 
      done = true; 
     } 
    } 
} 

Kết quả trên Windows XP 32-bit:

Windows XP 32-bit 
Intel Core2 Duo P8700 @ 2.53GHz 
BING(long)! 2161093208 > 2161092246, 962 
BING(long)! 2162448397 > 2161273312, 1175085 
BING(long)! 2270110050 > 2270109040, 1010 
BING(long)! 2270115061 > 2270110059, 5002 
BING(long)! 2558052223 > 2557528157, 524066 
BING(long)! 2571660540 > 2571659563, 977 
BING(long)! 2646433569 > 2646432557, 1012 
BING(long)! 2660841714 > 2660840732, 982 
BING(long)! 2661795522 > 2660841715, 953807 
BING(long)! 2712855281 > 2712854239, 1042 
BING(long)! 2737627472 > 2735210929, 2416543 
1025780885 =? 1073741823, 3168207035 =? 3221225470 

Chú ý cách Bing (int) không bao giờ được viết và chứng minh rằng 32-bit đọc/ghi là nguyên tử trên hệ điều hành 32 bit này.

Kết quả trên Windows 7 Enterprise 64-bit:

Windows 7 Enterprise 64-bit 
Intel Core2 Duo P8700 @ 2.53GHz 
BING(long)! 2208482159 > 2208121217, 360942 
BING(int)! 280292777 > 279704627, 588150 
BING(int)! 308158865 > 308131694, 27171 
BING(long)! 2549116628 > 2548884894, 231734 
BING(int)! 534815527 > 534708027, 107500 
BING(int)! 545113548 > 544270063, 843485 
BING(long)! 2710030799 > 2709941968, 88831 
BING(int)! 668662394 > 667539649, 1122745 
1006355562 =? 1073741823, 3154727581 =? 3221225470 

ý rằng Bing (dài) và Bing (int) đều hiển thị! Tại sao các hoạt động 32-bit bị lỗi, hãy để một mình các bit 64-bit?

+0

Có thể bạn có thể chỉnh sửa câu hỏi của mình để sử dụng định dạng 'Mẫu mã' trên thanh công cụ không? Thật khó đọc được .. – JBRWilkinson

+0

Tôi đã định dạng nó một cách chính xác nhưng với phông chữ TAB ban đầu thay vì không gian và bản xem trước trông tuyệt vời. Tôi đã bị sốc khi tôi phát hiện ra nó hoàn toàn thất bại khi đăng tải. Tôi đã sửa nó ngay bây giờ. –

+0

Tôi đã sửa nó: D – Femaref

Trả lời

4

Trong chủ đề callback của bạn, bạn đang làm nhiều hơn chỉ đơn giản là viết hoặc đọc:

++longValue; 
++intValue; 

Làm cả đọc và viết không thể đảm bảo được nguyên tử. Sử dụng Interlocked.Increment để đảm bảo nguyên tử của hoạt động này.

+0

Tôi không muốn những dòng này rõ ràng là nguyên tử. Tôi muốn hoạt động viết được đảm bảo nguyên tử bởi mô hình bộ nhớ. Đó là những gì tôi đang cố gắng chứng minh. Rõ ràng tôi nên sử dụng Interlocked.Increment (ref intValue hoặc longValue) nhưng điều đó sẽ đánh bại mục đích của cuộc biểu tình. –

+3

Các hoạt động viết là nguyên tử, đó là đọc + viết mà không phải là, như Darin nói. Vì vậy, nếu bạn đọc giá trị 5 trong chuỗi một, tăng nó lên 6, vì nó không phải là luồng nguyên tử 2 có thể có giá trị đọc 5 trong thời gian chờ đợi và đã tăng nó lên 6 hoặc nhiều hơn. Vì vậy, chuỗi 1 đang đặt lại giá trị về giá trị trước đó, giải thích hành vi bạn đang thấy. –

+0

@Julien Có, nhưng trường hợp đang được kiểm tra trong chủ đề Console.WriteLine chính là giá trị được ghi cuối cùng sẽ không bao giờ lớn hơn giá trị gần đây nhất. Bạn có thể giải thích sự khác biệt lớn về giá trị được nhìn thấy không? Đó là giá trị cuối cùng trong các dòng đầu ra. Nó không phải là một hoặc hai, nó trên thứ tự của 1.000 hoặc 100.000, cho thấy một số nghiêm trọng chút cắt xảy ra. –

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