PowerApps is built on JavaScript, which is single threaded (*), based on callbacks. Every expression is executed as a single "unit of execution", so if you have something like:
UpdateContext({ a: 1, b: 2 }); UpdateContext({ c: a + b })
You can count on the fact that the 'a' and 'b' will be initialized together (without being interrupted). You cannot, however, rely on the fact that the second UpdateContext call will be made before anything happens that may change the values of 'a' or 'b' (such as a timer's OnTimerEnd expression) - although it's very unlikely that this will happen.
For the specific example of timers, if you have two of them with this expression:
Set(globalVarA, globalVarA + 1)
It's possible (although quite unlikely, especially for this kind of simple operation) that the value of 'globalVarA + 1' will be calculated for the two timers before the internal implementation of the Set function is called to update the value of that variable (in which case the app would "lose" one of the increments).
A scenario where a problem is more likely to happen is when you have calls to data sources (which involve network calls that are slower). For example, if you have this expression on two timers:
Set(oldVar1, var1);
Patch(dataSource, record, changes);
Set(var1, oldVar1 + 1)
Then the likelihood of a race condition happening increases by a lot.
Hope this helps!
(*) Currently there is some very limited usage of JS worker threads, so the app isn't technically completely single threaded, but that should not affect expressions that you write.