4

How do I perform a lock based on a specific string-key?

public void PerformUpdate(string key)
{
    // TODO: Refine this, since they key-string won't 
    // be the same instance between calls

    lock(key)
    {
        PerformUpdateImpl()
    }
}

I've tried to keep lock-objects in a ConcurrentDictionary, but somehow this doesn't hold up either.

Patrick
  • 17,669
  • 6
  • 70
  • 85
Seb Nilsson
  • 26,200
  • 30
  • 103
  • 130
  • 1
    It locks by reference, the content is next to irrelevant. – Lloyd Nov 09 '12 at 12:11
  • @Lloyd What does that mean? That two different users/threads that pass the same text in the string, but not the same string, will still make above scenario work? – Seb Nilsson Nov 09 '12 at 12:13
  • 1
    Lock on a string is a very bad idea: See the remarks in sthe docs: http://msdn.microsoft.com/en-us/library/c5kehkcz(v=vs.100).aspx – Jan Nov 09 '12 at 12:14
  • 2
    Take a look at [stackoverflow.com/questions/4954626](http://stackoverflow.com/questions/4954626/how-lock-by-method-parameter) – KeyNone Nov 09 '12 at 12:15
  • 2
    @seb Strings are immutable so would present problems, see the link Jan provided. – Lloyd Nov 09 '12 at 12:17
  • @Jan I think that remark is only about constant strings though which reference the same object when compiling. – poke Nov 09 '12 at 12:21
  • @poke no, thats true for every string variable in your program. When the value is the same as your constant or variable lock string, its the same reference. – Jan Nov 09 '12 at 12:28
  • @poke Strings get interned, check out this - http://msdn.microsoft.com/en-us/library/system.string.intern.aspx – Lloyd Nov 09 '12 at 12:33
  • @Lloyd Interesting, didn’t know that. But still, the actual string references are different, and I can lock on a constant string and the same string built with a string builder just fine and they both work concurrently. So unless you explicitely lock on the intern string, this does not really work. – poke Nov 09 '12 at 12:42

2 Answers2

9

Although this isn't concurrent (you can make it so), what about Dictionary<string,object>.

Wouldn't this work?

dict.Add("somekey",new object());

lock (dict["somekey"]) {
  ...
}

This would allow a thread to lock a named instance of an object, which would I think do what you want.

Lloyd
  • 29,197
  • 4
  • 84
  • 98
  • Where would the `dict.Add` happen? It seems like this has the potential to cause race conditions on the dictionary. – Jeff B Jun 26 '14 at 16:22
  • 3
    Yes. I said it wasn't concurrent it was to just show a concept. You can get around this using `ConcurrentDictionary<>` with .NET 4 and beyond. – Lloyd Jun 26 '14 at 16:40
2

One way I've done something similar to this is by creating a Dictionary<string,object> and using this to go from the string to the object I am locking on. You may need to ensure that this dictionary is being accessed in a threadsafe fashion (eg a lock around it) and if you need to lock between different instances make it static, etc. But this is the broad technique I've used to do this.

Chris
  • 27,210
  • 6
  • 71
  • 92