Is there any way to lock on an integer in C#? Integers can not be used with lock because they are boxed (and lock only locks on references).
The scenario is as follo
Two boxed integers that happen to have the same value are completely indepent objects. So if you wanted to do this, your idea of Dictionary would probably be the way to go. You'd need to synchronize access to the dictionary to make sure you are always getting the same instance. And you'd have the problem of the dictionary growing in size.
You want to make sure that a delete doesn't happen twice?
CREATE PROCEDURE RemovePost( @postID int )
AS
if exists(select postID from Posts where postID = @postID)
BEGIN
DELETE FROM Posts where postID = @postID
-- Do other stuff
END
This is pretty much SQL server syntax, I'm not familiar with MyISAM. But it allows stored procedures. I'm guessing you can mock up a similar procedure.
Anyhow, this will work for the majority of cases. The only time it will fail is if two moderators submit at almost exactly the same time, and the exists() function passes on one request just before the DELETE statement executes on another request. I would happily use this for a small site. You could take it a step further and check that the delete actually deleted a row before continuing with the rest, which would guarantee the atomicity of it all.
Trying to create a lock in code, for this use case, I consider very impractical. You lose nothing by having two moderators attempting to delete a post, with one succeeding, and the other having no effect.
If it's a website then using an in-process lock probably isn't the best approach as if you need to scale the site out onto multiple servers, or add another site hosting an API (or anything else that would require another process accessing the same data to exist) then all your locking strategies are immediately ineffective.
I'd be inclined to look into database-based locking for this. The simplest approach is to use optimistic locking with something like a timestamp of when the post was last updated, and to reject updates made to a post unless the timestamps match.
I would personally go with either Greg's or Konrad's approach.
If you really do want to lock
against the post ID itself (and assuming that your code will only ever be running in a single process) then something like this isn't too dirty:
public class ModeratorUtils
{
private static readonly HashSet<int> _LockedPosts = new HashSet<int>();
public void ModeratePost(int postId)
{
bool lockedByMe = false;
try
{
lock (_LockedPosts)
{
lockedByMe = _LockedPosts.Add(postId);
}
if (lockedByMe)
{
// do your editing
}
else
{
// sorry, can't edit at this time
}
}
finally
{
if (lockedByMe)
{
lock (_LockedPosts)
{
_LockedPosts.Remove(postId);
}
}
}
}
}
C# locking is for thread safety and doesn't work the way you want it to for web applications.
The simplest solution is adding a column to the table that you want to lock and when somone locks it write to the db that that column is locked.
Dont let anyone open a post in edit mode if the column is locked for editing.
Otherwise maintain a static list of locked entry Ids and compare to that before allowing an edit.
Why don't you lock on the whole posting instead just on its ID?