.Net Meanderings

Richard Blewett's wanderings around .NET

Please read my disclaimer. Subscribe to my RSS feed

Thread Synchronization, Monitors and Domain Neutrality

During a thread on the Microsoft C# newsgroups someone was asking about whether they could use a Monitor for cross process synchronization. I replied stating that a Monitor was AppDomain specific and so no. Willy Denoyette (do you have a blog Willy?) replied and said “If you take a lock on a domain neutral type, you will get a cross-domain lock”. I’d completely forgotten about Domain Neutral assemblies and so it was great that Willy jumped in. However, I wanted to chase down the exact implications of this as Willy’s statement can be interpreted a couple of different ways.

So here is my test harness.

using System;
using System.Threading;

class App
{
  static object o = typeof(string);

  static void Main(string[] args)
  {
    AppDomain ad = AppDomain.CreateDomain("foo");
    ad.DoCallBack(new CrossAppDomainDelegate(Bar));
    Quux();
  }

  public static void Bar()
  {
    Thread th = new Thread(new ThreadStart(Quux));
    th.Start();           
  }

  static void Quux()
  {
    Thread.Sleep(1000);
    lock(o)
    {
      Console.WriteLine("In loc {0}",
                        AppDomain.CurrentDomain.FriendlyName);
      Thread.Sleep(3000);        
    }
    Console.WriteLine("Out of lock");
  }
}

 

In Main I call Bar in the other AppDomain. Bar calls Quux on another thread (so I can make the two blocks of code compete for what should be a common Monitor). Then I call Quux from Main in the default AppDomain.

Now, you should note that mscorlib is loaded domain neutral (only one copy is JIT’d and statics are shared across AppDomains. So for this exercise I will only use types from mscorlib.

I started off using the type object of System.String (as you can see above). This indeed exhibited the behavior Willy identified that this can be used as a cross-AppDomain locking target. This means the type object of types in domain neutral assemblies are shared by all AppDomains (which isn’t a problem as they are non-volatile).

Next I switched the line initializing o to

static object o =new object();

So now this is an instance of a type from an assembly loaded domain neutral. This resulted in no synchronization between the two AppDomains – and hopefully this is no great shock as most objects do not transcend AppDomain boundaries.

Now I switched to

static object o = typeof(App);

In other words, the type object of a type from a non-domain neutral assembly. This again gave no synchronization. Again, hopefully, not a shocking result.

Finally, what about statics, are they treated in any special way?. We need to find a type in mscorlib that has a public static property or field to get make this test case. Enter Environment.OSVersion a demand allocated reference type.

Changing my line again I get:

static object o = Environment.OSVersion;

And again no synchronization. Type objects are shared cross domain for domain neutral types - this is a special case and is known as Marshal-By-Bleed. Interned strings are also shared across AppDomains. In general, however, objects are not shared cross domain under any other circumstances.

12/21/2004 12:16 AM | Comments [1910] | #.NET

Content © 2003 Richard Blewett | Subscribe to my RSS feed.

Powered by BlogX