在没有获得锁的情况下测试锁?

时间:2010-02-18 23:13:46

标签: c# multithreading locking exit

我有物品,他们得到锁。我想测试他们是否被锁定而没有获得锁定。我的想法是TryEnter(),如果Exit()我必须true才能正确检查锁定。

似乎是一个非常基本的问题,它是如何完成的?

4 个答案:

答案 0 :(得分:22)

当您查看锁定 锁定时,您可以获得哪些可能的信息?当您根据该信息做出决定时,可能已经锁定了。

答案 1 :(得分:3)

因为lock语句等同于:

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

你能这样做吗?

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

请注意,我正在命名此函数“Object Unlocked”,而不是“ObjectIsUnlocked”。无法保证在函数返回时它仍然会被解锁。

答案 2 :(得分:3)

在尝试审核我的代码以进行正确锁定时,我想知道同样的事情。我想出了一个使用第二个线程的方法。如果锁可用于调用线程,但第二个线程不可用,则必须由第一个线程保持。

    /// <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"
}

我不会在生产代码中使用它 - 这种竞争条件可能会爆炸。但是,我的单元测试大多是单线程的,所以这很有用。

答案 3 :(得分:1)

这是一个相关的问题

Checking whether the current thread owns a lock

结论是“你不能”