共享资源锁

时间:2012-11-21 23:47:51

标签: c# asp.net thread-safety asp.net-web-api

我在.NET 4.5上使用C# - Web API Self Host。 服务器端我有一个非线程安全的进程:它可以一次处理一个请求。 如何在控制器代码中锁定此资源(进程),以便顺序提供客户端,等待资源在使用之前被释放? 类似的东西:

while(true){
    if(!process.isLocked)
        break;
}

lock(process)
do(work)
unlock(process)
warn(others)

感谢任何代码段或建议。提前谢谢。

2 个答案:

答案 0 :(得分:5)

如果您正在寻找要执行的每个线程,但一次只能查找一个,那么您可以将lock语句与静态对象一起使用:

private static object lockobj = new object();

public void DoWorkWhenNotBusy()
{
    lock (lockobj)
    {
        // do work
        Console.WriteLine("Working #1 (should always complete)...");
        Thread.Sleep(500);
    }
}

如果您希望线程在对象被锁定时立即返回,那么您可以这样写(双重检查锁定):

private static object lockobj2 = new object();
private volatile bool locked = false;

public void DoWorkIfNotBusy()
{
    if (!locked)
    {
        lock (lockobj2)
        {
            if (!locked)
            {
                locked = true;
                // do work
                Thread.Sleep(500);
                Console.WriteLine("Working #2 (only if not busy)...");
            }
            locked = false;
        }
    }
}

测试示例:

for (int i = 0; i < 10; i++)
{
    var ts = new ThreadStart(DoWorkWhenNotBusy);
    Thread t = new Thread(ts);
    t.Start();

    var ts2 = new ThreadStart(DoWorkIfNotBusy);
    Thread t2 = new Thread(ts2);
    t2.Start();

    Console.WriteLine("{0} started", i);
}

答案 1 :(得分:2)

我想在这里扩展dbaseman的答案。具体来说,他的DoWorkIfNotBusy方法。

我认为这是一个不好的例子(由于可能的竞争条件),并且想表明我认为正确方式的方式:

private static object lockobj = new object();

public bool DoWorkIfNotBusy()
{
    bool lockWasTaken = false;
    var temp = lockobj;
    try
    {
        Monitor.TryEnter(temp, ref lockWasTaken);
        {
            //Do work here.. 
            //Believe it or not, the brackets in which this work is in is important.
            //The brackets are to resolve a race condition.
        }
    }
    finally
    {
        if (lockWasTaken) Monitor.Exit(temp);
    }
    return lockWasTaken;
}