2010-03-09 24 views
10

Tôi có một hàm trả về một mục nhập trên một từ điển, dựa trên Khóa (tên) và nếu nó không tồn tại, trả về một từ mới được tạo.Khóa từ điển trong cùng một chủ đề

Câu hỏi tôi có là "khóa kép": SomeFunction khóa _dictionary, để kiểm tra sự tồn tại của khóa, sau đó gọi một hàm cũng khóa cùng một từ điển, có vẻ như hoạt động nhưng tôi không chắc chắn nếu có một vấn đề tiềm năng với phương pháp này.

public Machine SomeFunction(string name) 
{ 
    lock (_dictionary) 
    { 
     if (!_dictionary.ContainsKey(name)) 
        return CreateMachine(name); 
     return _dictionary[name]; 
    } 
} 


private Machine CreateMachine(string name) 
{ 
    MachineSetup ms = new Machine(name); 
    lock(_dictionary) 
    { 
     _ictionary.Add(name, ms); 
    } 
    return vm; 
} 
+8

Tôi nghĩ bạn hiểu lầm về việc khóa nào. Khóa ** chặn tất cả các chuỗi khác truy cập vào vùng mã được bảo vệ **. Nó không liên quan gì tới luồng * hiện tại *. Bạn có thể lấy ra một khóa một ngàn lần trên cùng một vật thể trên cùng một sợi, không thành vấn đề; mỗi khu vực mã bị khóa do đó sẽ được bảo vệ khỏi truy cập bởi các chủ đề khác. –

+0

Nếu bạn đang tìm kiếm "khóa cùng một luồng", hãy xem lớp [Semaphore] (http://msdn.microsoft.com/en-us/library/system.threading.semaphore.aspx). – ANeves

Trả lời

10

Đảm bảo công việc - khóa được đệ quy trong .NET. Cho dù đó thực sự là một ý tưởng tốt hay không là một vấn đề khác ... về việc này thay thế như thế nào:

public Machine SomeFunction(string name) 
{ 
    lock (_dictionary) 
    { 
     Machine result; 
     if (!_dictionary.TryGetValue(name, out result)) 
     { 
      result = CreateMachine(name); 
      _dictionary[name] = result; 
     } 
     return result; 
    } 
} 

// This is now *just* responsible for creating the machine, 
// not for maintaining the dictionary. The dictionary manipulation 
// is confined to the above method. 
private Machine CreateMachine(string name) 
{ 
    return new Machine(name); 
} 
+0

@Jon Skeet: Chỉ để xác minh cho bản thân mình, người ta không nên cố gắng để có được giá trị thay vì khóa từ điển ngay lập tức? Giống như bạn chỉ khóa khi phương thức TryGetValue() trả về false? –

+2

@Will Marcouiller - Đề án của bạn sẽ cho phép một chủ đề sửa đổi từ điển trong khi một chủ đề khác đang đọc nó. Nếu lớp từ điển được thiết kế đặc biệt để cho phép điều đó, thì một số lược đồ dọc theo các dòng đó có thể được thực hiện (với một TryGetValue thêm sau khi lấy khóa). Tuy nhiên, các bộ sưu tập thường không được thiết kế để sử dụng theo cách này, và lớp Từ điển được xây dựng trong là một trong những lớp không bao giờ được đọc và viết cùng một lúc. –

+0

Cảm ơn lời giải thích tuyệt vời này Jeffrey! Tôi đã tuyên thệ chính xác rằng một số đồng nghiệp của tôi đã sử dụng TryGetValue() trước và sau khi khóa() 'vào Bộ sưu tập. Điều này có thể đã được sử dụng xấu từ họ sau đó. Cảm ơn! Tôi sẽ nhớ điều đó. =) –

3

Không có vấn đề gì ở đây, khóa được tái nhập bởi cùng một sợi. Không phải tất cả các đối tượng đồng bộ đều có ái lực luồng, ví dụ như Semaphore. Nhưng Mutex và Monitor (khóa) vẫn ổn.

0

Mới kể từ .net 4.0, hãy kiểm tra ConcurrentDictionary - ConcurrentDictionary là một bộ sưu tập chủ đề an toàn của các cặp khóa/giá trị có thể được truy cập bởi nhiều chủ đề đồng thời. Thông tin thêm tại https://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx.

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