We should take a look at how MRI implements Thread.current and thread locals internally. It's likely that's not using any shared hash at all, so if we have our own global hash with a local around, surely that won't scale very well.

I'll commit using this approach since with a global counter it will work, and the counter shouldn't really be a problem unless we're allocating `ThreadLocalVar` in an inner loop, and then we can go back and look at it empirically. It's not much code to change if we find a better approach later.