18

I was reading about threading and about locking. It is common practise that you can't (well should not) lock a value type.

So the question is, what is the recommended way of locking a value type? I know there's a few ways to go about doing one thing but I haven't seen an example. Although there was a good thread on MSDN forums but I can't seem to find that now.

Thanks

lc.
  • 113,939
  • 20
  • 158
  • 187
GurdeepS
  • 65,107
  • 109
  • 251
  • 387
  • 2
    Are you 100% sure that you need to lock when modifying a value type object? When such a naked object is passed from one thread to the other, a copy is made, so the threads end up working on 2 different objects, which is safe. –  Jan 07 '09 at 16:52

4 Answers4

23

Use another object for the lock.

int valueType;
object valueTypeLock = new object();

void Foo()
{
    lock (valueTypeLock)
    {
        valueType = 0;
    }
}
Jon B
  • 51,025
  • 31
  • 133
  • 161
  • 6
    Remember to make the lock object readonly, or it can be changed to a different object. The shared lock assumption can go out of the window in this case. – Tim Lloyd May 15 '10 at 03:36
  • 1
    Note also that this particular example is strictly academic. No reasonable person would ever actually put a `lock` around a simple assignment of an `int` variable; the assignment is atomic, and ensuring up-to-date visibility of the write can be achieved more efficiently and easily by using the `volatile` keyword on the field declaration. – Peter Duniho Aug 23 '16 at 21:00
15

Your question is worded in such a way that it suggests to me that you don't entirely understand locking. You don't lock the data, you lock to protect the integrity of the data. The object you lock on is inconsequential. What matters is that you lock on the same object in other areas of your code that alter the data being protected.

Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393
2

Depend on your situation you might be able to avoid using locks by leveraging System.Threading.Interlocked the same code in Jon's example becomes:

System.Threading.Interlocked.Exchange(valueType,0)
JoshBerke
  • 66,142
  • 25
  • 126
  • 164
0

I'm always using a separate variable to lock on:

object syncObj = new object();

void Foo()
{
  lock(syncObj)
  {
    // do some stuff
  }
}

Locking on value-types doesn't make sense anyway because value-types are immutable and can't be modified. Locking on 'this' is also problematic because 'this' is visible to the outer world.

For some information about how the Monitor was originally intended to be used see Monitor (synchronization)

Thomas Danecker
  • 4,635
  • 4
  • 32
  • 31
  • Err, value-type objects aren't really immutable. When I say int i=0; ++i; I've just modified a value-type object. –  Jan 07 '09 at 16:32
  • 2
    no, you assigned a new value to the variable, but you didn't mutate the value-type. value-types are 'values'. 1 is always 1. 1+1 is the value 2 but you don't change the value 1 to 2. you could modify composite value-types (aka structs) though that's also considered as (very) bad practice. – Thomas Danecker Jan 08 '09 at 22:23
  • _"value-types are immutable and can't be modified"_ -- this is true for primitive value types, but not value types in general. Value types _should_ be implemented as immutable, but many are not (e.g. [Rectangle](https://msdn.microsoft.com/en-us/library/system.drawing.rectangle(v=vs.110).aspx)). In any case, it's not the immutability (or not) of a value type that's why locking on such a type doesn't make sense. It's that you _can't_ lock on a value type, because it has no monitor. I find this answer very inaccurate and misleading. – Peter Duniho Aug 23 '16 at 20:58