views:

82

answers:

2
+1  Q: 

Does lock allocate

I read somewhere, although I can't remember where, that using the lock keyword in C# can allocate.

I know that trying to lock a ValueType will box the valuetype, but are there any other situations?

EDIT::

  1. Everyone seems to be answer the valuetype case, I already know this!
  2. I also know what locks are and how to use them in great depth, general advice on best practice is nice - but useless ;)
  3. I need to know because I'm building an XNA app for deployment on the xbox. The xbox garbage collector is really slow - this means I need to keep allocations to a minimum, preferably non-existent (which prevents the collector from ever running)
+1  A: 

While the allocation of see sync block internally is lazy (but that's an implementation detail which IIRC I know from Essential.NET 'volume 1', or is it CLR via C# - and should be treated as just that), the simple case of the item needing to be boxed like you're suggesting doesn't arise - see http://stackoverflow.com/questions/1329919/why-lockinteger-var-is-not-allowed-but-monitor-enterinteger-var-allowed

Ruben Bartelink
Ok, so that confirms that locking a value type *does* allocate, but what about locking a reference type?
Martin
@Martin: 1. you cant lock a value type - you would need to box it and 'lock the box'. 2. Regarding references, it allocates something internally [which is null until its needed], but it's not a .NET object it's an internal structure that the CLR owns. You shouldnt see an impact in a .NET profiler for instance - though mem usage at native level might be affected. Which brings us to 'what do you need to know for' ?
Ruben Bartelink
updated with some new information
Martin
@Martin: As I said - the allocations that happen are definitely not CLR allocations in terms of affecting GC, so no - it shouldnt affect that. What I'm talking about it is a simple internal implementation detail - i.e., it doesnt go doing anything stupid like allocating a Win32 Critical Section for every object just because in theory any reference object is lockable. While I'm not CLR internals guru, I'm confident enough about this fact to not pull the Esential .NET book from the other end of my tabell to look it up :P
Ruben Bartelink
Ok, so I'm going to take it as a given that lock doesn't allocate. I don't suppose you have any references for this stuff? :/
Martin
Will look in Essential.NET tomorrow and post.
Ruben Bartelink
in E.NET p79 and p197-8 it talks about sync blocks and that they're created on demand - it's pretty clear these are internal structures managed by the CLR rather than Objects subject to GC. Havent looked in CLR via C#. Tried usign a memory profiler like the red gate one to prove your theory (not necessarily directly against XNA, on an representative extracted portion of your code)
Ruben Bartelink
+1  A: 

If you were thinking of using:

lock(this)

You should know that because you're looking on your instance, users of your class could also lock on it and screw you up. Whether or not that is an issue depends on what you think your users might do. The same situation exists if you're doing:

lock(typeof(MyClass))

If you don't want to do this, you can easily allocate a static or instance object (ie object myLock = new object()), and then lock on that.

Source

As far as locking on a reference type vs value type, this SO question on Locking a resource when obtained... has the answer:

It depends on the type - if a reference type then yes, if a value type no. This is also why you should never, ever lock on a value type since the value type will be boxed and any subsequent attempts to lock on that value will actually acquire a lock on a different object.

Definition of lock statement:

lock Statement (C# Reference)

The lock keyword marks a statement block as a critical section by obtaining the mutual-exclusion lock for a given object, executing a statement, and then releasing the lock.

This SO question on lock keyword in C# may be able to help. You can also look at Why lock() is not allowed, but Monitor.Enter() allowed?

The specification for the compiler defines the behavior of lock like so:

The compile time type of the expression of a lock statement shall be a reference-type or a > type parameter (§25.1.1) known to be a reference type. It is a compile-time error for the compile time type of the expression to denote a value-type.

0A0D
That tells me lots of general information about locks. But it still doesn't answer the real question. I want to know if a lock allocates *when locking a reference type*. If you read my question I said I *already know* about locking value types :P
Martin
@Martin: I can't find anything that says it does.
0A0D