Shared Resource Lock

喜你入骨 提交于 2019-12-22 17:17:49

问题


I'm using C# on .NET 4.5 - Web API Self Host. Server-side I've a process that is not thread safe: it can serve one request at a time. How can I lock this resource (process) in the controller code, so that clients are served sequentially, waiting for the resource to be freed before using it? Something like:

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

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

Any code snippet or suggestion are appreciated. Thanks in advance.


回答1:


If you're looking for each thread to execute, but only one at a time, then you can use the lock statement with a static object:

private static object lockobj = new object();

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

If you want the thread to return immediately if the object is locked, then you can write it like this (double-checked locking):

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;
        }
    }
}

Test example:

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);
}



回答2:


I would like to expand on dbaseman's answer here. Specifically, his DoWorkIfNotBusy method.

I think that is a bad example (due to possible race conditions), and would like to show the way I think the correct way would be:

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;
}


来源:https://stackoverflow.com/questions/13503912/shared-resource-lock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!