Now hopefully I won't get horribly dinged for mistakes and poor advice here. What I am trying to say is that I too read "even senior devs don't understand the race conditions they create downstream." And I thought - oh God, don't I.
But five minutes thought can help you walk through most issues. For most applications most of the time you can reason your way through without fear, and when you do encounter gnarly problems they often can go away by redesigning your application! Often the problems you encounter you caused. retrace your steps and find an easier path. Save the hard thinking for genuine problems / value creation.
So race conditions are simply when two processes / threads are likely to affect a single resource. In this case it's a file - and the problem is test if a file exists, then if it does not, create it and then write to it.
If two threads do this, say a log file, the first one creates the file and logs it's important stuff, the second then creates it again wiping out the first log data.
Solutions in this area include
- create as append file (the concept is basically deviates old because this is a decades old problem)
- avoid sharing resources. for logging log to per thread locations. Not always possible but you sure as hell can minimise this to one or two resources you must share.
- hand off creating files to a seperate part of the application. There is a balance between "scripting" and "application" and using small little library functions to do in one line indirectly something that also takes one line using the methods shown in the docs.
- handing off batons / mutexes etc etc. This gets wildly complex. Honestly given a world of async libraries, Erlang, and distributed computing, if you find yourself having to use multi-threading think very carefully if this is the right approach.
Yeah that's more or less "don't do simple one liners in your application code - write a simple library that does the simple thing, but wraps the simple thing in lots of checks"
There probably is a "design pattern" for that but darned if I can draw it in UML
But five minutes thought can help you walk through most issues. For most applications most of the time you can reason your way through without fear, and when you do encounter gnarly problems they often can go away by redesigning your application! Often the problems you encounter you caused. retrace your steps and find an easier path. Save the hard thinking for genuine problems / value creation.
So race conditions are simply when two processes / threads are likely to affect a single resource. In this case it's a file - and the problem is test if a file exists, then if it does not, create it and then write to it.
If two threads do this, say a log file, the first one creates the file and logs it's important stuff, the second then creates it again wiping out the first log data.
Solutions in this area include
- create as append file (the concept is basically deviates old because this is a decades old problem)
- avoid sharing resources. for logging log to per thread locations. Not always possible but you sure as hell can minimise this to one or two resources you must share.
- hand off creating files to a seperate part of the application. There is a balance between "scripting" and "application" and using small little library functions to do in one line indirectly something that also takes one line using the methods shown in the docs.
- handing off batons / mutexes etc etc. This gets wildly complex. Honestly given a world of async libraries, Erlang, and distributed computing, if you find yourself having to use multi-threading think very carefully if this is the right approach.