Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

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.



For the example in question one approach which might work well is to realize the test is superfluous. Just open the file with the right flags.

That is, the flag for create if not already existing and flaf for deny sharing so any other process/thread will fail to concurrently open it.

Then you just handle the case when the open fails.

Of course this relies on those flags being available and working. For example shared files might not respect the sharing lock.

Many cases of avoiding race conditions boil down to something similar: avoid the problem by not doing extra work.


Or, sidestep it by creating an empty log file (if it doesn't exist) during initialization before creating multiple threads.


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




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: