Fun with Threads and Closures

(empirical programming — try something, see what happens, guess what the compilers are doing)

Here is a broken program:

    class Program
    {
        static void Main(string[] args)
        {
            for (var i = 0; i < 40; i++)
            {
                new Thread(() => { Thread.Sleep(1); Console.Write("{0} ", i); }).Start();
            }
            Console.WriteLine();
        }
    }

It’s broken because the inner lambda expression refers to the variable i, which can have any old value between 0 and 40 INCLUSIVE. Using i as an array index would probably generate a bounds exception. The lambda expression will likely see many repetitions of the same value of i, yadda yadda. It’s junk.

Now press the magic "refactor / extract method" button, and get a program that works (after a suitable warning that semantics might change — but, of course, that’s exactly what we want: the semantics to change from INCORRECT to CORRECT):

    class Program
    {
        static void Main(string[] args)
        {
            for (var i = 0; i < 40; i++)
            {
                g(i);
            }
            Console.WriteLine();
        }

        private static void g(int i)
        {
            new Thread(() => { Thread.Sleep(1); Console.Write("{0} ", i); }).Start();
        }
    }

The lambda expression now produces a permutation of the integers between 0 and 39, and that’s just fine.

But, I’m scared because I thought the stack variables, in this case, the int i argument of g, would go away by the time the lambda expression were called, so the compiler is probably making nice copies of them somewhere. No, and I’m just lucky? Boxing? Not sure what’s going on, but rather not look a gift horse in the mouth, as they say.

Advertisements

~ by rebcabin on April 15, 2008.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: