2010-04-22 27 views
8

Chi phí thực hiện có sử dụng khóa lồng nhau cho cùng một đối tượng không.Khóa lồng vào cùng một hiệu năng đối tượng

Giả sử chúng ta có:

public void AddRange(IEnumeratable<Item> items) 
    { 
     lock (_syncObject) 
     { 
      foreach (Item item in items) 
      { 
       InsertItem(item); 
      } 
     } 
    } 

    public void InsertItem(Item item) 
    { 
     lock (_syncObject) 
     { 
      //.. 
     } 
    } 

Is it ok để làm như vậy "phía bên thực hiện"?

Xin cảm ơn trước.

Trả lời

6

Khóa có chi phí, tôi đề nghị bạn thực hiện mã của bạn như thế này:

public void AddRange(IEnumeratable<Item> items) 
{ 
    lock (_syncObject) // Locking only once. 
    { 
     foreach (Item item in items) 
     { 
      InsertItemImpl(item); 
     } 
    } 
} 

private void InsertItemImpl(Item item) 
{ 
    // inserting the item 
} 

public void InsertItem(Item item) 
{ 
    lock (_syncObject) 
    { 
     InsertItemImpl(item); 
    } 
} 
2

lock không miễn phí. nó để kiểm tra một số thứ trước khi trở về. Làm thế nào nhiều điều và những gì nó đã làm, phụ thuộc vào thực hiện. Tôi sẽ đoán rằng loại hình sử dụng này phổ biến và MS đã thực hiện một số tối ưu hóa cho việc sử dụng này.

Tôi vẫn khuyên bạn nên triển khai AddRange riêng biệt với tất cả những việc đã thực hiện trong một lần chụp. Điều này tất nhiên phụ thuộc vào phần còn lại của giao diện của lớp (là có thính giả và họ có thể nhận được tin nhắn rằng một số đối tượng đã được thêm vào vv).

Đây là testcase khá dễ dàng, thực hiện hàng triệu khóa lồng nhau (những gì bạn đề xuất) và giống với khóa khác.

Thông báo cũng có thể thứ tự khác nhau nếu bạn sử dụng khóa không lồng nhau, bạn có thể nhận được một đối tượng ở giữa của một loạt bạn đang thêm:

AddRange _sync1 
    AddItem _sync2 
    AddItem _sync2 
    --- interruption, other thread calls: 
    AddItem _sync2 
    --- AddRange again: 
    AddItem _sync2 

Khi đồng bộ với một _syncObject duy nhất, không ai có thể gián đoạn bởi vì khóa đã được giữ bởi một sợi khác.

1

Tôi không biết làm thế nào hiệu suất bị ảnh hưởng, nhưng khi chúng tôi hy vọng nó sẽ làm giảm hiệu suất tôi muốn đề nghị bạn thực hiện mã của bạn theo cách khác xung quanh:

public void InsertItem(Item item) 
{ 
    AddRange(new IEnumeratable({item})) 
} 

public void AddRange(IEnumeratable<Item> items) 
{ 
    lock (_syncObject) 
    { 
     foreach (Item item in items) 
     { 
      // Insert code .. 
     } 
    } 
} 

@AddRange (mới IEnumeratable ({ item})): Tôi không phải là một cú pháp wizkid vì vậy hãy sửa tôi nếu điều này không đúng!

+3

tôi nghĩ rằng nó là tốt hơn để di chuyển ra Insert thực hiện đến một phương pháp thay sau đó tạo ra bộ sưu tập mới cho từng hạng mục bổ sung. –

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