Câu trả lời:
lock
là một từ khóa trình biên dịch, không phải là một lớp hoặc đối tượng thực tế. Đó là một trình bao bọc xung quanh chức năng của Monitor
lớp và được thiết kế để làm việc Monitor
dễ dàng hơn với trường hợp thông thường.
Các Monitor
(và các lock
từ khóa) là, như Darin nói, hạn chế đến AppDomain
. Chủ yếu bởi vì tham chiếu đến một địa chỉ bộ nhớ (ở dạng đối tượng được khởi tạo) là bắt buộc để quản lý "khóa" và duy trì danh tính củaMonitor
Mặt Mutex
khác, là một trình bao bọc .Net xung quanh cấu trúc hệ điều hành và có thể được sử dụng để đồng bộ hóa toàn hệ thống, sử dụng dữ liệu chuỗi (thay vì con trỏ tới dữ liệu) làm định danh. Hai mutex tham chiếu hai chuỗi trong hai địa chỉ bộ nhớ hoàn toàn khác nhau, nhưng có cùng dữ liệu , sẽ thực sự sử dụng cùng một mutex hệ điều hành.
A Mutex
có thể là cục bộ của một quá trình hoặc toàn hệ thống . MSDN :
Mutexes có hai loại: mutexes cục bộ, không được đặt tên và mutexes hệ thống được đặt tên. Một mutex cục bộ chỉ tồn tại trong quá trình của bạn.
Hơn nữa, người ta cũng cần đặc biệt cẩn thận - chi tiết trên cùng một trang - khi sử dụng một mutex toàn hệ thống trên một hệ thống với Terminal Services.
Một trong những khác biệt giữa Mutex
và lock
là Mutex
sử dụng cấu trúc cấp kernel , do đó, đồng bộ hóa sẽ luôn yêu cầu ít nhất một chuyển đổi không gian kernel-kernel.
lock
- đó thực sự là một lối tắt đến Monitor
lớp , mặt khác cố gắng tránh phân bổ tài nguyên kernel và chuyển sang mã kernel (và do đó gọn hơn & nhanh hơn - nếu người ta phải tìm một cấu trúc WinAPI giống với nó, thì nó sẽ như vậy CriticalSection
).
Sự khác biệt khác là những gì người khác chỉ ra: một cái tên Mutex
có thể được sử dụng trên các quy trình.
Trừ khi một người có nhu cầu đặc biệt hoặc yêu cầu đồng bộ hóa qua các quy trình, tốt hơn hết là bạn nên bám vào lock
(aka Monitor
)
Có một số khác biệt "nhỏ" khác, như cách xử lý từ bỏ, v.v.
Điều tương tự cũng có thể nói về ReaderWriterLock
và ReaderWriterLockSlim
trong 3.5, Semaphore
và mới SemaphoreSlim
trong .NET 4.0, v.v ... Đúng là các xxSlim
lớp sau không thể được sử dụng như một nguyên hàm đồng bộ hóa toàn hệ thống, nhưng chúng không bao giờ có nghĩa - chúng chỉ "có nghĩa" để nhanh hơn và thân thiện hơn với tài nguyên.
Tôi sử dụng Mutex để kiểm tra xem tôi đã có bản sao của ứng dụng đang chạy trên cùng một máy chưa.
bool firstInstance;
Mutex mutex = new Mutex(false, @"Local\DASHBOARD_MAIN_APPLICATION", out firstInstance);
if (!firstInstance)
{
//another copy of this application running
}
else
{
//run main application loop here.
}
// Refer to the mutex down here so garbage collection doesn't chuck it out.
GC.KeepAlive(mutex);
Rất nhiều điều đã được nói, nhưng để làm cho nó đơn giản, đây là của tôi.
khóa -> Sử dụng đơn giản, trình bao bọc trên màn hình, khóa trên các luồng trong AppDomain.
mutex chưa được đặt tên -> tương tự như khóa ngoại trừ phạm vi khóa là nhiều hơn và nó nằm trên AppDomain trong một quy trình.
Mutex được đặt tên -> phạm vi khóa thậm chí còn nhiều hơn mutex không tên và nó xuyên suốt quá trình trong một hệ điều hành.
Vì vậy, bây giờ các tùy chọn đã có, bạn cần chọn một trong những phù hợp nhất trong trường hợp của bạn.
Mutex là một quá trình chéo và sẽ có một ví dụ kinh điển về việc không chạy nhiều hơn một phiên bản của một ứng dụng.
Ví dụ thứ hai là bạn đang có một tệp và bạn không muốn có quá trình khác nhau để truy cập cùng một tệp, bạn có thể triển khai Mutex nhưng hãy nhớ một điều Mutex là một hệ điều hành rộng và không thể sử dụng giữa hai quy trình từ xa.
Khóa là một cách đơn giản nhất để bảo vệ phần mã của bạn và nó là tên miền cụ thể, bạn có thể thay thế khóa bằng Moniter nếu bạn muốn đồng bộ hóa được kiểm soát nhiều hơn.
Một số khác biệt nhỏ hơn không được đề cập trong các câu trả lời:
Trong trường hợp sử dụng khóa, bạn có thể chắc chắn rằng khóa sẽ được giải phóng khi có ngoại lệ xảy ra bên trong khối khóa.
Đó là bởi vì khóa sử dụng màn hình dưới mui xe và được thực hiện theo cách này :
object __lockObj = x;
bool __lockWasTaken = false;
try
{
System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
// Your code...
}
finally
{
if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
}
Do đó, trong mọi trường hợp, khóa được phát hành và bạn không cần phải giải phóng nó một cách thủ công (giống như bạn làm cho các trường hợp đột biến).
Đối với Khóa, bạn thường sử dụng một đối tượng riêng để khóa (và nên sử dụng ).
Điều này được thực hiện vì nhiều lý do. (Thông tin thêm: xem câu trả lời này và tài liệu chính thức ).
Vì vậy, trong trường hợp khóa, bạn không thể (vô tình có được) quyền truy cập vào đối tượng bị khóa từ bên ngoài và gây ra một số thiệt hại.
Nhưng trong trường hợp Mutex, bạn có thể, vì thông thường có một Mutex được đánh dấu công khai và được sử dụng từ bất cứ đâu.