Simplify your locking strategy -- simpler is better

Well I didn't mean to but it seems I'm writing a series of articles on locking. 

Based on my last posting I got several requests for a simple example of a case that could be improved with simpler locking.  Here's something of that ilk that's similar to something I encountered in The Real World.  The 2nd choice is based on what I recommended.

 

     class FreeThreaded1
    {
        private static volatile Dictionary  dict = new Dictionary();

        static void UpdateThreadProc() // one thread runs this
        {
            for (;;)
            {
                using (StreamReader sr = new StreamReader("c:\\pickupdir\\dictionary.txt"))
                {
                    lock (dict)
                    {
                        dict.Clear();

                        String line = null;

                        while (null != (line = sr.ReadLine()))
                        {
                            int iTab = line.IndexOf('\t');

                            if (iTab < 1 || iTab > line.Length-2)
                                continue;

                            string key = line.Substring(0, iTab);
                            string val = line.Substring(iTab+1);

                            dict.Add(key, val);
                        }
                    }
                }

                System.Threading.Thread.Sleep(5000);
            }
        }

        static string ReadEntry(string s)  // this is called by many threads at random
        {
            lock (dict)
            {
                return dict[s];
            }
        }
    }


    class FreeThreaded2
    {
        private static volatile Dictionary  dict = new Dictionary();

        static void UpdateThreadProc() // one thread runs this
        {
            for (;;)
            {
                using (StreamReader sr = new StreamReader("c:\\pickupdir\\dictionary.txt"))
                {
                    Dictionary d = new Dictionary();
                    String line = null;

                    while (null != (line = sr.ReadLine()))
                    {
                        int iTab = line.IndexOf('\t');

                        if (iTab < 1 || iTab > line.Length-2)
                            continue;

                        string key = line.Substring(0, iTab);
                        string val = line.Substring(iTab+1);

                        d.Add(key, val);
                    }
                    dict = d;
                }

                System.Threading.Thread.Sleep(5000);
            }
        }

        static string ReadEntry(string s)  // this is called by many threads at random
        {
            return dict[s];
        }
    }

Can you spot at least 3 reasons why I would like the 2nd one better? Not that it's perfect...