Ai đó có thể giải thích sự khác biệt giữa:
- khóa (someobject) {}
- Sử dụng Mutex
- Sử dụng Semaphore
- Sử dụng màn hình
- Sử dụng các lớp đồng bộ hóa .Net khác
Tôi không thể tìm ra nó. Dường như với tôi hai cái đầu giống nhau?
Ai đó có thể giải thích sự khác biệt giữa:
Tôi không thể tìm ra nó. Dường như với tôi hai cái đầu giống nhau?
Câu trả lời:
Câu hỏi tuyệt vời. Tôi có thể sai .. Hãy để tôi thử .. Bản sửa đổi số 2 trong câu trả lời gốc của tôi .. với một chút hiểu biết hơn. Cảm ơn đã khiến tôi đọc :)
khóa (obj)
Màn hình
Sử dụng khóa hoặc màn hình rất hữu ích để ngăn chặn việc thực thi đồng thời các khối mã nhạy cảm với luồng, nhưng các cấu trúc này không cho phép một luồng truyền thông một sự kiện đến một sự kiện khác. Điều này đòi hỏi các sự kiện đồng bộ hóa , là các đối tượng có một trong hai trạng thái, được báo hiệu và không có tín hiệu, có thể được sử dụng để kích hoạt và tạm dừng các luồng. Mutex, Semaphores là các khái niệm cấp hệ điều hành. ví dụ: với một mutex có tên, bạn có thể đồng bộ hóa qua nhiều exes (được quản lý) (đảm bảo rằng chỉ một phiên bản ứng dụng của bạn đang chạy trên máy.)
Đột biến:
Semaphores (làm tổn thương não của tôi).
Monitor
không cho phép giao tiếp là không chính xác; bạn vẫn có thể Pulse
vv với mộtMonitor
Re "Sử dụng các lớp đồng bộ hóa .Net khác" - một số trong những lớp khác bạn nên biết về:
Ngoài ra còn có nhiều cấu trúc khóa (chi phí thấp) trong CCR / TPL ( CTP mở rộng song song ) - nhưng IIRC, chúng sẽ được cung cấp trong .NET 4.0
Như đã nêu trong ECMA và như bạn có thể quan sát từ các phương thức Reflected, câu lệnh khóa về cơ bản tương đương với
object obj = x;
System.Threading.Monitor.Enter(obj);
try {
…
}
finally {
System.Threading.Monitor.Exit(obj);
}
Từ ví dụ đã nói ở trên, chúng ta thấy rằng Màn hình có thể khóa trên các đối tượng.
Mutexe là hữu ích khi bạn cần đồng bộ hóa quá trình vì chúng có thể khóa trên một định danh chuỗi. Cùng một quy trình nhận dạng chuỗi có thể được sử dụng bởi các quy trình khác nhau để có được khóa.
Semaphores giống như Mutexes trên steroid, chúng cho phép truy cập đồng thời bằng cách cung cấp số lượng truy cập đồng thời tối đa '. Khi đạt đến giới hạn, semaphore bắt đầu chặn mọi quyền truy cập vào tài nguyên cho đến khi một trong những người gọi giải phóng semaphore.
Tôi đã hỗ trợ các lớp & CLR cho luồng trong DotGNU và tôi có một vài suy nghĩ ...
Trừ khi bạn yêu cầu khóa quá trình chéo, bạn nên luôn luôn tránh sử dụng Mutex & Semaphores. Các lớp trong .NET này là các hàm bao quanh Win32 Mutex và Semaphores và có trọng lượng khá nặng (chúng yêu cầu chuyển đổi ngữ cảnh sang Kernel đắt tiền - đặc biệt là nếu khóa của bạn không bị tranh chấp).
Như những người khác được đề cập, câu lệnh khóa C # là ma thuật trình biên dịch cho Monitor. Entry và Monitor.Exit (tồn tại trong một lần thử / cuối cùng).
Màn hình có cơ chế tín hiệu / chờ đơn giản nhưng mạnh mẽ mà Mutexes không có thông qua các phương thức Monitor.Pulse / Monitor.Wait. Tương đương Win32 sẽ là các đối tượng sự kiện thông qua CreatEvent, thực tế cũng tồn tại trong .NET với tên WaitHandles. Mô hình Pulse / Wait tương tự như pthread_signal và pthread_wait của Unix nhưng nhanh hơn vì chúng có thể hoàn toàn là các hoạt động ở chế độ người dùng trong trường hợp không tranh chấp.
Monitor.Pulse / Wait rất đơn giản để sử dụng. Trong một luồng, chúng ta khóa một đối tượng, kiểm tra cờ / trạng thái / thuộc tính và nếu đó không phải là điều chúng ta mong đợi, hãy gọi Monitor.Wait sẽ giải phóng khóa và đợi cho đến khi một xung được gửi. Khi chờ đợi trở lại, chúng tôi lặp lại và kiểm tra lại cờ / trạng thái / thuộc tính. Trong luồng khác, chúng tôi khóa đối tượng bất cứ khi nào chúng tôi thay đổi cờ / trạng thái / thuộc tính và sau đó gọi PulseAll để đánh thức mọi luồng nghe.
Thông thường chúng tôi muốn các lớp của chúng tôi là luồng an toàn vì vậy chúng tôi đặt các khóa trong mã của chúng tôi. Tuy nhiên, thường thì lớp chúng ta sẽ chỉ được sử dụng bởi một luồng. Điều này có nghĩa là các khóa không cần thiết làm chậm mã của chúng tôi ... đây là nơi tối ưu hóa thông minh trong CLR có thể giúp cải thiện hiệu suất.
Tôi không chắc chắn về việc triển khai khóa của Microsoft nhưng trong DotGNU và Mono, cờ trạng thái khóa được lưu trữ trong tiêu đề của mọi đối tượng. Mọi đối tượng trong .NET (và Java) có thể trở thành một khóa vì vậy mọi đối tượng cần hỗ trợ điều này trong tiêu đề của chúng. Trong triển khai DotGNU, có một cờ cho phép bạn sử dụng hàm băm toàn cầu cho mọi đối tượng được sử dụng làm khóa - điều này có lợi ích là loại bỏ chi phí 4 byte cho mọi đối tượng. Điều này không tốt cho bộ nhớ (đặc biệt là đối với các hệ thống nhúng không được phân luồng nhiều) nhưng lại ảnh hưởng đến hiệu năng.
Cả Mono và DotGNU đều sử dụng hiệu quả các mutexes để thực hiện khóa / chờ nhưng sử dụng so sánh và trao đổi kiểu spinlock hoạt động để loại bỏ nhu cầu thực sự thực hiện khóa cứng trừ khi thực sự cần thiết:
Bạn có thể xem một ví dụ về cách màn hình có thể được thực hiện ở đây:
http://cvs.savannah.gnu.org/viewvc/dotgnu-pnet/pnet/engine/lib_monitor.c?revision=1.7&view=markup
Một cảnh báo bổ sung để khóa trên bất kỳ Mutex được chia sẻ nào mà bạn đã xác định bằng ID chuỗi là nó sẽ mặc định là một mutex "Local \" và sẽ không được chia sẻ giữa các phiên trong môi trường máy chủ đầu cuối.
Tiền tố định danh chuỗi của bạn với "Toàn cầu \" để đảm bảo quyền truy cập vào tài nguyên hệ thống được chia sẻ được kiểm soát chính xác. Tôi vừa gặp phải một đống vấn đề khi đồng bộ hóa thông tin liên lạc với một dịch vụ chạy trong tài khoản HỆ THỐNG trước khi tôi nhận ra điều này.
Tôi sẽ cố gắng tránh "lock ()", "Mutex" và "Monitor" nếu bạn có thể ...
Kiểm tra không gian tên mới System.Collections.Conc hiện tại .NET 4
Nó có một số lớp bộ sưu tập an toàn chủ đề đẹp
http://msdn.microsoft.com/en-us/l Library / system.collections.concản.aspx
Đồng thời đá từ! không khóa tay nữa cho tôi!
Trong hầu hết các trường hợp, bạn không nên sử dụng khóa (= Màn hình) hoặc mutexes / semaphores. Tất cả đều chặn luồng hiện tại.
Và bạn chắc chắn không nên sử dụng System.Collections.Concurrent
các lớp - chúng là nguồn chính của các điều kiện chủng tộc vì không hỗ trợ giao dịch giữa nhiều bộ sưu tập và cũng chặn chuỗi hiện tại.
Đáng ngạc nhiên là .NET không có cơ chế hiệu quả để đồng bộ hóa.
Tôi đã triển khai hàng đợi nối tiếp từ GCD ( Objc/Swift
thế giới) trên C # - rất nhẹ, không chặn công cụ đồng bộ hóa sử dụng nhóm luồng, với các bài kiểm tra.
Đó là cách tốt nhất để đồng bộ hóa mọi thứ trong hầu hết các trường hợp - từ truy cập cơ sở dữ liệu (xin chào sqlite) đến logic kinh doanh.