2013-04-08 35 views
9

Tôi đang cố gắng Tăng phần tử trong danh sách trong C#, nhưng tôi cần nó là luồng an toàn, vì vậy số lượng không bị ảnh hưởng.Chủ đề an toàn Gia tăng trong C#

Tôi biết bạn có thể làm điều này cho số nguyên:

Interlocked.Increment(ref sdmpobjectlist1Count);

nhưng điều này không làm việc trên một danh sách tôi đã sau cho đến nay:

lock (padlock) 
{ 
    DifferenceList[diff[d].PropertyName] = DifferenceList[diff[d].PropertyName] + 1; 
} 

Tôi biết điều này, nhưng Tôi không chắc liệu có cách nào khác để làm điều này không?

+14

Tại sao bạn cần một cách khác, nếu cách này hoạt động? –

+0

Bạn đang tìm kiếm một cơ chế khóa không độc quyền? –

+0

http://msdn.microsoft.com/en-us/library/system.threading.monitor.aspx – CSharpie

Trả lời

1

Như David Heffernan cho biết, ConcurrentDictionary sẽ cung cấp hiệu suất tốt hơn. Tuy nhiên, hiệu suất đạt được có thể là không đáng kể tùy thuộc vào mức độ thường xuyên nhiều chủ đề cố gắng truy cập bộ nhớ cache.

using System; 
using System.Collections.Concurrent; 
using System.Threading; 

namespace ConcurrentCollections 
{ 
    class Program 
    { 
     static void Main() 
     { 
      var cache = new ConcurrentDictionary<string, int>(); 

      for (int threadId = 0; threadId < 2; threadId++) 
      { 
       new Thread(
        () => 
        { 
         while (true) 
         { 
          var newValue = cache.AddOrUpdate("key", 0, (key, value) => value + 1); 
          Console.WriteLine("Thread {0} incremented value to {1}", 
           Thread.CurrentThread.ManagedThreadId, newValue); 
         } 

        }).Start(); 
      } 

      Thread.Sleep(TimeSpan.FromMinutes(2)); 
     } 
    } 
} 
+0

Chức năng cập nhật không phải là nguyên tử trong cuộc gọi AddOrUpdate. https://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx – Ryan

+0

Nhận xét đó chỉ có nghĩa là 'mã có thể chạy nhiều lần trước khi thành công'. Nó chạy bên ngoài khóa, về cơ bản. Vì vậy, nó nhận được giá trị hiện tại, thêm 1 vào nó, lấy ra một khóa và sau đó cố gắng viết nó trở lại. Nếu giá trị hiện tại đã thay đổi trong thời gian chờ đợi, nó sẽ lặp lại quá trình cho đến khi nó thành công. – mjwills

-1

kiểm tra biến bạn đã khóa trên "padLock", thông thường, bạn có thể xác định biến là private static Object padLock = new Object(). nếu bạn không định nghĩa nó là tĩnh, mỗi đối tượng có bản sao riêng của nó, do đó nó sẽ không hoạt động.

+4

Nó phụ thuộc vào dữ liệu. Nếu dữ liệu không tĩnh thì không cần đối tượng khóa tĩnh; bạn sẽ không cần đồng bộ hóa với các chuỗi không cố gắng truy cập cùng một dữ liệu. – Servy

1

Nếu bạn sử dụng một List<int[]> chứ không phải là một List<int>, và mỗi phần tử trong danh sách là một mảng đơn hàng, bạn sẽ có thể làm Increment(ref List[whatever][0]) và có nó được nguyên tử. Người ta có thể nâng cao hiệu quả lưu trữ hơi nếu một định nghĩa

class ExposedFieldHolder<T> {public T Value;} 

và sau đó sử dụng một List<ExposedFieldHolder<int>> và sử dụng báo cáo kết quả thực hiện Increment(ref List[whatever].Value) thặng dư. Mọi thứ có thể hiệu quả hơn nếu các kiểu dựng sẵn cung cấp phương tiện để lộ một mục như là một lớp bắt buộc có thể truy cập vào nội bộ của chúng để cung cấp khả năng như vậy. Tuy nhiên, chúng không thể xác định các loại bộ sưu tập của riêng mình từ đầu hoặc đóng gói từng mục trong đối tượng lớp riêng của nó [sử dụng một mảng hoặc một lớp trình bao bọc].

+0

Trừ khi bạn có một số lý do rất cụ thể để viết bộ sưu tập an toàn chủ đề của riêng bạn trong hầu hết các trường hợp, bạn sẽ tốt hơn nhiều so với một trong những được cung cấp với TPL. –