[Mono-list] Class library developers: locking issues to keep in mind

Miguel de Icaza miguel@ximian.com
31 Oct 2001 21:45:31 -0500


On Sun, 2001-10-28 at 20:05, Serge wrote:
> > making reference volatile does not save you from the situation
> > when the reference is OK, but the object it points to has not been
> > completely initialized
> 
> That's right, it wont help. This is true for both UP and MP machines.
> As long as constructor inlining is a valid optimization for JIT (and I
> suppose it is).

I am sorry, but I keep missing this point.  Why would an object not be
completely initialized before the actual pointer is updated?

The object needs to be initialized before its return value is assigned
to a variable or a register (and hence where the flush to main memory is
required).

> However, I have an idea for DCL replacement.
> Why not use function pointers (or delegates) to replace the original
> (locked) initializer after its first execution with empty non-synched
> method?

Although this works, my worries with this sample is that it suffers from
the same problems that were discussed earlier.  The code is horrible to
read, let alone easy to figure out for someone who is there just
browsing the code.

As I can see, from a pure maintenance point of view, I like the
suggestion that you or Alex had.  For now lets just wrap the entire
class in a lock method, like this:

string MyProperty {
   get {
	lock (typeof (this)){
		if (cache == null)
			cache = create_heavy_object ();
		return cache;
	}
   }
}

This has a number of advantages:

	* It is not a pre-optimization.

	  My previous example was a pre-optimization on a class library,
	  to avoid extra locking steps. 

	* We could make Threading.Monitor.Enter very efficient (indeed, 	  the
JIT engine could inline the code completely if required) 	  so it might
not even become an issue in the long run.

	* For maintainers the rule is very simple: do not try to predict 	  for
now what is going to be a bottleneck and what is not.  

The #ifdef solution that Rhys suggested might work, but I have a strong
dislike for any code that contains #ifdefs, I rather work out other
solutions like an attribute in the future, or fine tuning those parts
that require to be fine tuned and using any kind of barrier emission at
that point (even if it looks ugly) in a few isolated cases, rather than
complicating the code now.

The other issue is that at this point it is not clear which libraries in
.NET are thread safe and which ones are not.  In some cases the
framework assumes that you would be providing the locking yourself, and
in others not.  I do not know what the rationale has been for it.

I think I am going to start maintaining a document that keeps track of
these issues, and serves as a reference for contributors working on the
class libraries (how to handle errors, internationalization, locking,
etc).


Miguel.