This is fine when that design pattern fits the domain. But some domains require global context, and it isn't useful or possible to strictly enforce separation - because you end up passing parameter bundles around and managing all those local scopes introduces more bugs than implementing a global context.
Multithreading is a different issue, and is a different kind of domain requirement. If you need multithreading and have a global context, you have a very interesting problem to solve.
Well, yes, but then the unit tests end up taking twenty minutes.
Don't restart the program between tests. Randomize the order of the test cases between runs. Try running the same test multiple times on occasion.
To that end, if you have variables that live as long as your program, or longer, have your tests reflect that.
Globals are bad because they are just often used poorly. In large because they require you to think about the whole system as you make changes.
Ironically, the best changes are done with the whole system in mind. Such that sometimes establishing a few core globals and some rules for how they will be treated can actually help your logic. So it really is a tradeoff. With a great slogan of "think globally, but act locally."