2010-02-18 31 views
8

Tôi có đồ vật, chúng có khóa. Tôi muốn kiểm tra nếu chúng bị khóa mà không có khóa. Ý tưởng là nếu tôi TryEnter() họ tôi phải Exit() nếu đúng để chỉ kiểm tra khóa một cách chính xác.Kiểm tra khóa có mua nó không?

Có vẻ như một câu hỏi thực sự cơ bản, nó được thực hiện như thế nào?

Trả lời

22

Thông tin nào bạn có thể nhận được khi biết khóa mở khóa lại khi bạn nhìn vào nó? Vào thời điểm bạn đưa ra quyết định dựa trên thông tin đó, khóa có thể đã được thực hiện.

+3

+1, chính xác. Trả lời câu hỏi này về trạng thái quá khứ của khóa chỉ có thể khiến bạn đưa ra quyết định không chính xác. – JaredPar

+0

Tôi khóa mọi thứ để tôi có thể xem chúng có đang được sử dụng hay không. ví dụ. Vì vậy, hai chủ đề không đập vỡ các tài nguyên được chia sẻ giống nhau. Tôi muốn xem liệu công việc đó có đang được thực hiện hay không. Tôi có thể làm điều tương tự với một giá trị IsBeingUsed nhưng đối tượng cho khóa đã tồn tại và các khóa hoạt động theo cùng một cách, ngoại trừ việc có thể kiểm tra xem chúng có bị khóa không khi đặt giá trị bị khóa. – QueueHammer

+3

Khi bạn kiểm tra IsBeingUsed, luồng có thể đã dừng công việc hữu ích nhưng một chuyển đổi ngữ cảnh có thể đã xảy ra trước khi IsBeingUsed được cập nhật. –

2

Bởi vì báo cáo kết quả khóa tương đương với:

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

Bạn có thể chỉ làm điều này?

bool ObjectWasUnlocked(object x) 
{ 
    if(System.Threading.Monitor.TryEnter(x)) 
    { 
     System.Threading.Monitor.Exit(x); 
     return true; 
    } 
    else 
    { 
     return false; 
    } 
} 

Lưu ý rằng tôi đặt tên chức năng này "Object Đã Unlocked" như trái ngược với "ObjectIsUnlocked". Không có gì đảm bảo rằng nó vẫn sẽ được mở khóa khi chức năng đã trở lại.

+0

Trong giải pháp này mặc dù bạn có được khóa đó là một cái gì đó OP không muốn làm. – JaredPar

+0

@JaredPar: Đúng, tốt. –

3

tôi đã tự hỏi điều tương tự khi cố gắng kiểm toán mã của tôi cho khóa chính xác. Tôi đã đưa ra một phương pháp bằng cách sử dụng một chuỗi thứ hai. Nếu khóa có sẵn cho chuỗi cuộc gọi, nhưng không có sẵn cho chuỗi thứ hai, nó phải được giữ bởi chuỗi đầu tiên.

/// <summary> 
/// Utiltity for checking if a lock has already been acquired. 
/// WARNING: This test isn't actually thread-safe, 
/// it's only really useful for unit tests 
/// </summary> 
private static bool ObjectIsAlreadyLockedByThisThread(object lockObject) 
{ 
    if (!Monitor.TryEnter(lockObject)) 
    { 
     // another thread has the lock 
     return false; 
    } 

    Monitor.Exit(lockObject); 

    bool? LockAvailable = null; 

    var T = new Thread(() => 
    { 
     if (Monitor.TryEnter(lockObject)) 
     { 
      LockAvailable = true; 
      Monitor.Exit(lockObject); 
     } 
     else 
     { 
      LockAvailable = false; 
     } 
    }); 

    T.Start(); 

    T.Join(); 

    return !LockAvailable.Value; 
} 

// Tests: 
public static void TestLockedByThisThread() 
{ 
    object MyLock = new object(); 
    lock (MyLock) 
    { 
     bool WasLocked = ObjectIsAlreadyLockedByThisThread(MyLock); 

     Debug.WriteLine(WasLocked); // prints "True" 
    } 
} 

public static void TestLockedByOtherThread() 
{ 
    object MyLock = new object(); 

    var T = new Thread(() => 
    { 
     lock (MyLock) 
     { 
      Thread.Sleep(TimeSpan.FromSeconds(2)); 
     } 
    }); 

    T.Start(); 
    Thread.Sleep(TimeSpan.FromSeconds(1)); 

    bool WasLocked = ObjectIsAlreadyLockedByThisThread(MyLock); 

    T.Join(); 

    Debug.WriteLine(WasLocked); // prints "False" 
} 

public static void TestNotLocked() 
{ 
    object MyLock = new object(); 

    bool WasLocked = ObjectIsAlreadyLockedByThisThread(MyLock); 

    Debug.WriteLine(WasLocked); // prints "False" 
} 

Tôi sẽ không sử dụng mã này trong mã sản xuất - có điều kiện chạy đua có thể phát nổ. Tuy nhiên, các bài kiểm tra đơn vị của tôi chủ yếu là các luồng đơn, vì vậy điều này rất hữu ích.

+0

Mã này bị hỏng. Đầu tiên 'Monitor.Exit (lockObject)' (trong khối 'finally') được gọi ngay cả khi khóa không thể có được. –

+0

@ Sebastian Krysmanski: điểm tốt, không cần cuối cùng. cố định và dọn dẹp – GranBurguesa

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