> What are the implications of identifying a scenario where there is no race condition?
No race condition? Great. It's totally possible there are some not-so-concurrent parts of your software that can run in what I deem a performant manner.
> Does it just result in a performance hit?
It's much more than that. A bug I have is very serious and it goes something like this: you set a limit order to buy X shares. The limit order gets a partial fulfillment, and you immediately set stop losses and take profits for X shares. However, the limit order gets complete fulfillment before the two other requests are done. If you now try to update the previous orders, for example, it might be that the update call gets registered at the broker first, but the creation gets there last, which means you have bought X+Y shares, but you have stop losses and take profits for only the X. You might now completely lose Y unless you monitor the software all the time. Things like these might happen everywhere, and the real trouble starts when these instances with plausible race conditions of their own start communicating with other parts which might also have race conditions.
And the requirement for the concurrency is not only a performance: you might want to collect data in thread N, while you have different strategies of amount M, which all by default subscribe to N, but only selectively when they are doing their strategies. In such a sense, I don't think that doing even a semi-serious trading software without concurrency is possible.
Go for example has a race condition detector built in to the tool chain (go run/test/build --race). They won’t tell you how to fix it, but they’ll tell you which lines are in the critical region that the programmer missed.
Go’s support for race detectors is super ergonomic. You need a unit test for the parent function that’s spawning the routines. Run that unit test with the race flag, and it’ll catch it for you. If you’re curious about how it works, this post is good: https://blog.golang.org/race-detector