2013-01-17 18 views
7

Tôi có tình huống sau: Tôi muốn chung loại trừ quyền truy cập vào một đối tượng.Có thể khóa và giám sát được sử dụng trên cùng một đối tượng an toàn không?

Cho đến nay tôi normaly sẽ sử dụng một đối tượng khóa

object lockObject = new object(); 
... 

method1: lock(lockObject) { CODE1 } 

Bây giờ tôi cũng có một phương pháp có thể được gọi từ thread khác. Nó không nên bị chặn trong thời gian không xác định, thay vào đó nó sẽ đưa ra một câu trả lời trong một thời gian xác định.

Trong trường hợp này tôi sẽ sử dụng một màn hình, giống như

method2: 
try{ 
    Monitor.TryEnter(lockObject , 20000, ref lockTaken); 
    if (lockTaken) {CODE2} 
} 
catch(...){...} 
finally 
{ 
    if (lockTaken) Monitor.Exit(timerLock); 
} 

Bây giờ câu hỏi của tôi là: có thể khóa và màn hình được trộn lẫn theo cách như vậy nếu lockobject là như nhau và cùng loại trừ lẫn nhau, hoặc sẽ nó là cần thiết để thay đổi mọi khóa cho một màn hình.

Vì vậy, cả hai lần cùng một mã thông báo sẽ bị "khóa" hoặc màn hình sẽ tạo một mã thông báo khác cho đối tượng thì khóa?

Nhìn thoáng qua, tôi không thể thấy rằng ứng dụng chạy trong mã của cả hai cùng một lúc. Nhưng tôi không biết nếu bất kỳ vấn đề thời gian có thể tồn tại, nơi CODE1 và CODE2 được thực thi song song.

+1

Tôi cảm thấy đau đớn của bạn; Tôi thường muốn từ khóa 'lock' mất một thời gian chờ bằng cách nào đó bằng cách nào đó –

Trả lời

6
lock (sync) 
{ 
    return World(); 
} 

Hãy xem các dòng này bằng ngôn ngữ trung gian.

L_0007: call void [mscorlib]System.Threading.Monitor::Enter(object) 
L_000c: call int32 Hello::World() 
L_0011: stloc.0 
L_0012: leave.s L_001b 
L_0014: ldloc.1 
L_0015: call void [mscorlib]System.Threading.Monitor::Exit(object) 

Vì vậy, nó sẽ ổn. Chúng tương đương về mặt kỹ thuật.

+0

lưu ý rằng các phiên bản csc gần đây, khi nhắm mục tiêu .NET 4 trở lên, sẽ có IL khác nhau cho số này –

+0

Cảm ơn, đúng. Chỉ cần làm nó cho minh họa thô. –

5

có thể khóa và theo dõi được trộn theo cách như vậy nếu lockobject là như nhau và cùng loại trừ nhau

Vâng, đó là hoàn toàn an toàn và nó sẽ làm việc.

Câu lệnh lock { } được viết lại để gọi đến Monitor.Enter() và Monitor.Exit(). Nó chỉ ngắn gọn, rất giống với tuyên bố using() {}.

Từ MSDN:

lock (x) ... 

trở thành

System.Threading.Monitor.Enter(x); 
try { 
    ... 
} 
finally { 
    System.Threading.Monitor.Exit(x); 
} 

Và theo nhận xét, trong Fx4 và sau đó nó có thể sử dụng Monitor.TryEnter(). Nhưng phiên bản đơn giản ở trên trả lời câu hỏi của bạn.

+2

Hoặc Monitor.TryEnter khi nhắm mục tiêu .NET 4+. –

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