2015-09-16 14 views
5

Tôi gặp khó khăn khi hiểu tại sao đa luồng không cập nhật được giá trị trước khi chuỗi hoàn tất. Chuỗi riêng có bản sao tham chiếu hoặc giá trị riêng không?
Vấn đề đa luồng cập nhật giá trị

Nếu không, để hiểu biết của tôi mã dưới đây sẽ hoạt động đúng khi MyMethod được gọi, nhưng thường nó không tạo ra các trường hợp của một số đối tượng MyType trong mảng trước khi thread.IsAlive trở thành sai:

class MyClass 
{ 
    static MyType[] obj = new MyType[Environment.ProcessorCount - 1]; 
    void MyMethod() 
    { 
     Thread[] threads = new Thread[Environment.ProcessorCount - 1]; 

     for (int i = 0; i < Environment.ProcessorCount - 1; i++) 
     { 
      threads[i] = new Thread(() => FillObjects(i)); 
      threads[i].Priority = ThreadPriority.AboveNormal; 
      threads[i].Start(); 
     } 

     while (threads[i].Any(c => c.IsAlive)) 
     { 
      Thread.Sleep(50); 
     } 
    } 
    void FillObjects(int i) 
    { 
     obj[i] = new MyType(); 
     //perform actions with obj[i] to fill it with necessary values 
    } 
} 

Trả lời

6

Bạn cần gán giá trị của biến vòng lặp cho biến cục bộ. Nếu không, có thể việc thực thi đầu tiên của FillObjects(i) được thực hiện sau khi i được tăng lên để FillObjects(0) không bao giờ được gọi và do đó obj[0] không bao giờ được gán.

void MyMethod() 
{ 
    Thread[] threads = new Thread[Environment.ProcessorCount - 1]; 

    for (int i = 0; i < Environment.ProcessorCount - 1; i++) 
    { 
     int local = i; 
     threads[i] = new Thread(() => FillObjects(local)); 
     threads[i].Priority = ThreadPriority.AboveNormal; 
     threads[i].Start(); 
    } 

    while (threads.Any(c => c.IsAlive)) 
    { 
     Thread.Sleep(50); 
    } 
} 
+2

Điểm tốt. Nếu câu lệnh đầu tiên trong 'FillObjects()' là 'Thread.Sleep (1000)' có lẽ chỉ 'obj [Environment.ProcessorCount - 1]' sẽ không null vì vòng lặp sẽ tăng lên 'i' đến giá trị cuối của nó. trước khi đối tượng đầu tiên được tạo. Suy nghĩ về nó, FillObjects() có thể ném bởi vì 'i' thực sự được tăng lên đến' Environment.ProcessorCount-1' trước khi thoát khỏi vòng lặp và do đó nằm ngoài giới hạn của 'obj'. –

+0

Cảm ơn bạn đã trả lời, thực sự đó là một trong những vấn đề lớn, bây giờ nó instantiates các đối tượng đúng cách. Tuy nhiên, thread không hoàn thành tất cả các hoạt động đúng trước khi nó tắt và thực hiện điều này một cách ngẫu nhiên. Bất kỳ đề xuất? – Almis

+0

Tôi đã tìm thấy sai lầm hợp lý của riêng mình, bây giờ nó hoạt động đúng. – Almis

-1

Trên một máy đa xử lý (mà bạn phải có) kết quả được ghi vào một vị trí bộ nhớ trong một luồng có thể không hiển thị trong một luồng khác do bộ nhớ đệm. Sử dụng Thread.VolatileReadThread.VolatileWrite đọc để đọc và ghi "thông qua" bộ nhớ cache.

Cf. the chapter on threading in c# 3.0 in a Nutshell để được giải thích. (Hãy tìm câu hỏi "Có thể cho phương thức Chờ để viết" Sai "không?". Ví dụ đó về cơ bản là trường hợp của bạn.)

+0

Hết sức tò mò: Điều gì sai hoặc không áp dụng cho những gì tôi đã nói? –

+0

Mặc dù không phải là một trong đó downvoted: Tôi không thể nghĩ ra một kịch bản sử dụng volatileRead/Write để giải quyết vấn đề trên. Các vấn đề tham chiếu từ C# trong IMHO nutshell không phù hợp với vấn đề trên cũng như tôi không thấy bất kỳ vấn đề bộ nhớ đệm mà dễ bay hơi sẽ giải quyết. – Linky

+0

@Linky Hm. Đó là hai chủ đề vừa truy cập vào biến tĩnh. Một chủ đề "đã viết" cho nó (được chỉ ra bởi một sự kiện sau đó trong chủ đề đó). Chủ đề khác đọc giá trị đã được viết từ phối cảnh của chuỗi viết và không thấy ghi. Trông tôi giống như kịch bản ở đây. –

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