Mike Norgate
Mike Norgate

Reputation: 2431

Conditional locking based on value

I am writing a web service that allows users to create jobs within the system. Each user has an allowance of the number of jobs they can create. I have a method which checks that the user has some remaining credits which looks like this:

private bool CheckRemainingCreditsForUser(string userId)
{
    lock(lockObj)
    {
       var user = GetUserFromDB(userId);
       if (user.RemaingCredit == 0) return false;
       RemoveOneCreditFromUser(user);
       SaveUserToDB(user);
    }
}

The problem I can see with this approach is that if multiple different users make a request at the same time they will only get processed one at a time which could cause performance issues to the client. Would it be possible to do something like this?

private bool CheckRemainingCreditsForUser(string userId)
{
    //If there is a current lock on the value of userId then wait 
    //If not get a lock on the value of userId
    var user = GetUserFromDB(userId);
    if (user.RemaingCredit == 0) return false;
    RemoveOneCreditFromUser(user);
    SaveUserToDB(user);
    //Release lock on the value of userId
}

This would mean that requests with different userIds could be processed at the same time, but requests with the same userId would have to wait for the previous request to finish

Upvotes: 2

Views: 1135

Answers (2)

Henk Holterman
Henk Holterman

Reputation: 273229

Yes, you could do that with a Dictionary<string, object>. To link a lockObject to every userId.

The problem would be cleaning up that Dictionary every so often.

But I would verify first that there really is a bottleneck here. Don't fix problems you don't have.

The alternative is to have a (optimistic) concurrency check in your db and just handle the (rare) conflict cases.

Upvotes: 1

Ethenyl
Ethenyl

Reputation: 684

Instead of locking in every methods, why aren't you using a Singleton that will manage the User's rights ?

It will be responsible from giving the remaining allowances AND manage them at the same time without loosing the thread-safe code.

By the way, a method named CheckRemainingCreditsForUser should not remove allowances since the name isn't implying it, you may be the only developer on this project but it won't hurt to make 2 methods to manage this for re-useability and code comprehension.

EDIT : And this object should also hold the Users dictionary

Upvotes: 0

Related Questions