2009-09-22 28 views
42

Cụ thểChủ đề chuỗi C# có an toàn không?

  1. Tạo hàm để lấy mảng và chỉ mục làm tham số.
  2. Tạo mảng phần tử n.
  3. Tạo vòng lặp đếm n.
  4. Bên trong vòng lặp trên một chủ đề mới gán một thể hiện mới của các đối tượng đến các mảng bằng cách sử dụng chỉ mục thông qua vào.

tôi biết làm thế nào để quản lý các đề vv Tôi quan tâm đến bí quyết nếu đây là chủ đề cách an toàn để làm điều gì đó.

class Program 
{ 
    // bogus object 
    class SomeObject 
    { 
     private int value1; 
     private int value2; 

     public SomeObject(int value1, int value2) 
     { 
      this.value1 = value1; 
      this.value2 = value2; 
     } 
    } 

    static void Main(string[] args) 
    { 

     var s = new SomeObject[10]; 
     var threads = Environment.ProcessorCount - 1; 
     var stp = new SmartThreadPool(1000, threads, threads); 
     for (var i = 0; i < 10; i++) 
     { 
      stp.QueueWorkItem(CreateElement, s, i); 
     } 

    } 

    static void CreateElement(SomeObject[] s, int index) 
    { 
     s[index] = new SomeObject(index, 2); 
    } 
} 
+20

Đây hoàn toàn không phải là điểm của câu hỏi, nhưng tôi khuyên bạn không nên sử dụng 'Environment.ProcessorCount - 1' - những người nghèo đơn lõi này sẽ hết sức không hài lòng nếu không ... –

+6

Có những người có đơn bộ xử lý lõi? – Gary

+4

@Gary có các máy ảo có bộ xử lý "một";) – IamIC

Trả lời

39

Tôi tin rằng nếu mỗi chuỗi chỉ hoạt động trên một phần riêng biệt của mảng, tất cả sẽ tốt. Nếu bạn đang truy cập , hãy chia sẻ dữ liệu (ví dụ: giao tiếp giữa các chủ đề) thì bạn sẽ cần một số loại rào cản bộ nhớ để tránh các vấn đề về mô hình bộ nhớ.

tôi tin rằng nếu bạn đẻ trứng một loạt các chủ đề, mỗi trong số đó populates phần riêng của mảng, sau đó chờ cho tất cả những chủ đề để kết thúc sử dụng Thread.Join, rằng sẽ làm đủ về các rào cản đối với bạn được an toàn. Tôi không có bất kỳ tài liệu hỗ trợ nào cho điều đó vào lúc này, hãy nhớ bạn ...

EDIT: Mã mẫu của bạn an toàn. Không bao giờ có hai luồng truy cập cùng một phần tử - nó giống như là mỗi luồng có các biến riêng biệt. Tuy nhiên, điều đó không có xu hướng hữu ích một mình. Tại một số điểm bình thường các chủ đề sẽ muốn chia sẻ nhà nước - một trong những chủ đề sẽ muốn đọc những gì người khác đã viết. Nếu không thì không có điểm nào trong đó viết vào một mảng được chia sẻ thay vì vào các biến riêng của riêng chúng. Đó là điểm mà tại đó bạn cần phải cẩn thận - sự phối hợp giữa các chủ đề.

+3

Các phần tử mảng tuân theo các quy tắc tương tự như các biến thông thường, trong đó hoán đổi một tham chiếu sẽ là nguyên tử nhưng thay thế một cấu trúc nói chung sẽ không được. Tuy nhiên, điều này không tính đến sự cần thiết của một rào cản bộ nhớ, để làm cho các truy cập dễ bay hơi. Như bạn đã nói, cho dù đó là an toàn sẽ phụ thuộc chính xác vào những gì các coder đang làm. –

+0

@Steven: Yup, đó là về sự hiểu biết của tôi :) –

+2

@Steven "cho dù đó là an toàn sẽ phụ thuộc chính xác vào những gì các coder đang làm." - Không giống như nói "Không, không an toàn." ? – Rik

24

MSDN documentation on Arrays nói:

tĩnh công cộng (chung trong Visual Basic) thành viên của loại này là chủ đề an toàn. Bất kỳ thành viên nào không phải là được đảm bảo là chuỗi an toàn.

Triển khai này không cung cấp trình bao bọc đồng bộ (ren an toàn) cho một mảng; tuy nhiên, các lớp .NET Framework dựa trên Array cung cấp phiên bản đồng bộ của riêng bộ sưu tập bằng cách sử dụng thuộc tính SyncRoot .

Liệt kê thông qua bộ sưu tập là thực chất không phải là thủ tục an toàn thread . Ngay cả khi một bộ sưu tập là được đồng bộ, các chủ đề khác vẫn có thể sửa đổi bộ sưu tập, điều này gây ra điều tra viên để ném ngoại lệ. Để đảm bảo an toàn luồng trong khi điều chỉnh , bạn có thể khóa bộ sưu tập trong toàn bộ số điều tra hoặc bắt ngoại lệ do các thay đổi được thực hiện bởi các chủ đề khác.

Vì vậy, không, chúng không phải là chủ đề an toàn.

+13

Điều này không trả lời được câu hỏi của tôi. Tôi không làm bất kỳ điều tra nào như thế nào anh chàng này có thể nhận được 13 phiếu bầu? – Gary

+4

Phiếu bầu có nghĩa là câu trả lời hữu ích. Dấu kiểm của bạn cho biết câu trả lời giải quyết được vấn đề của bạn. Với thông tin này, nếu tôi đang phát triển một lớp có thể tạo luồng với mảng, tôi tin rằng điều đầu tiên tôi sẽ làm là kích hoạt Reflector, mở một trong các lớp Framework sử dụng Array trong bối cảnh an toàn chủ đề và xem chúng đang làm gì với SyncRoot. –

+6

Câu trả lời này thực sự không hữu ích, cũng như báo MSDN khá gây hiểu lầm * và * không phải vấn đề. Mảng truy cập vào các kiểu tham chiếu là nguyên tử; thậm chí liệt kê trên một mảng như vậy (trong khi có lẽ không khôn ngoan) là đến mức độ an toàn thread. –

11

Thông thường khi bộ sưu tập được gọi là 'không an toàn' có nghĩa là truy cập đồng thời có thể bị lỗi nội bộ (ví dụ: không an toàn để đọc phần tử đầu tiên trong Danh sách < T> trong khi một chuỗi khác thêm phần tử vào cuối danh sách: Danh sách < T> có thể thay đổi kích cỡ mảng cơ bản và quyền truy cập đọc có thể đi tới mảng mới trước khi dữ liệu được sao chép vào nó).

Lỗi như vậy là không thể với mảng vì mảng có kích thước cố định và không có 'thay đổi cấu trúc' như vậy. Một mảng có ba phần tử không an toàn hơn hoặc ít hơn so với ba biến.

Đặc tả C# không nói gì về điều này; nhưng rõ ràng nếu bạn biết IL và đọc đặc tả CLI - bạn có thể nhận được một tham chiếu được quản lý (giống như tham chiếu được sử dụng cho tham số C# "ref") cho một phần tử bên trong một mảng và sau đó thực hiện cả tải bình thường và biến động và lưu trữ nó. Thông số CLI mô tả các đảm bảo an toàn luồng cho các tải trọng và các cửa hàng đó (ví dụ: nguyên tử cho các phần tử < = 32 bit)

Vì vậy, nếu tôi hiểu câu hỏi của bạn một cách chính xác, bạn muốn điền vào một mảng bằng cách sử dụng các chủ đề khác nhau. chỉ định mỗi phần tử mảng một lần? Nếu vậy, đó là hoàn toàn an toàn thread.

4

Ví dụ bạn đang cung cấp rất giống với cách mà các phần mở rộng song song của Microsoft đối với công việc C# 4.0.

này cho vòng lặp:

for (int i = 0; i < 100; i++) { 
    a[i] = a[i]*a[i]; 
} 

trở thành

Parallel.For(0, 100, delegate(int i) { 
    a[i] = a[i]*a[i]; 
}); 

Vì vậy, có, ví dụ của bạn nên được OK. Đây là số blog post cũ hơn về hỗ trợ song song mới trong C#.

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