问题
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