3
public abstract class Comparer<T> : IComparer, IComparer<T>
    {
        static Comparer<T> defaultComparer;    

        public static Comparer<T> Default {
            get {
                Comparer<T> comparer = defaultComparer;
                if (comparer == null) {
                    comparer = CreateComparer();
                    defaultComparer = comparer;
                }
                return comparer;
            }
        }

First, is the Default property thread safe? Isn't it possible that effect of the following statement

comparer = CreateComparer(); 

might not be visible to threads other than creating thread? So, multiple instances of Comparer are constructed?

Is Microsoft doing this for the sake of trading synchronization cost off with the cost of creating multiple objects?

Second why defaultComparer is first assigned to comparer variable first...and then later on swapped? why do Comparer comparer = defaultComparer?

Brian Gideon
  • 47,849
  • 13
  • 107
  • 150
drr
  • 91
  • 1
  • 4

2 Answers2

1

Yes. Multiple comparers do indeed get created, defaultComparer gets assigned multiple times. Not a problem, they are all the same. The garbage collector takes care of the extras. And the atomic assignment guarantee that the CLR offers for object references ensures that the static cannot be read incorrectly.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Ok. but why this dance with, first assigning Comparer comparer = defaultComparer and then swapping later...can't one simplly do if (defaultComparer == null) {defaultComparer = CreateComparer(); return defaultComparer? } – drr Mar 16 '11 at 23:49
  • It takes less machine code bytes to do it this way. The static, which needs 4 address bytes, is only accessed twice. – Hans Passant Mar 17 '11 at 00:08
  • oh you mean that accessing static has less cost than accessing thread local? how so? – drr Mar 17 '11 at 00:22
  • Also, how does .NET memory model play into this? – drr Mar 17 '11 at 00:25
  • It is not thread local, just local. Use Debug + Windows + Assembly to see this stuff for yourself. – Hans Passant Mar 17 '11 at 00:32
  • I meant to say local (thread local was mistyping)..Will look into the assembly – drr Mar 17 '11 at 00:37
  • Thanks a lot. I did compare the assembly code. And the above implementation is more space efficient. – drr Mar 17 '11 at 00:53
0

Yes, it certainly is possible that multiple instances of the comparer are created. Before you can answer whether or not the Default property is thread-safe we should probably define what we want to be safe. If you only ever want a single instance to be created then it certainly is not thread-safe. However, if you relax your requirement to allow for multiple instances as long as some instance is returned then it certainly does that.

I would say the reasoning behind this decision was based partly on the fact that the IComparer instance is stateless. That means from a callers perspective it really does not matter which instance the caller grabs because they all look and operate the same. In other words, it really would not matter if a single thread repeatedly read Default and got a different instance each time.

Brian Gideon
  • 47,849
  • 13
  • 107
  • 150