Any thread/process may create the file but must be prepared to handle "file already exists" error if another thread/process is creating the file one microsecond before. In that context, file already exists is not an error!
Then every thread/process lock the file BEFORE writing or reading anything and unlock right after.
Now the question is where to lock. File locking allow to lock one or more bytes, and even lock a non existent part of the file. There are several possibilities. The most important is that every thread/process must follow the same rule.
1) Lock the whole file and way past the end of file.
2) Lock a single bytes or a few bytes, usually the the file header, if any.
3) Lock from the byte at end of file for a large block.
4) Lock a single byte far away from end of file, at a fixed place that will never be reached.
5) Another file, maybe empty, is used to place the locks.
Solution 1 is easy and the file is completely locked for everything except the one that placed the lock. This include any editor or even the "type" or "copy" commands of the command interpreter. This may be desirable... or not.
Solution 2 is frequently used by database manager.
Solution 3 will allow reading from a thread/process for the existing part of the file while another is appending to the file.
Solution 4 is interesting in some cases because any reader/writer will be able to read/write to the file as usual but all aware of the locking will correctly write to the file without overwriting anything. This may be desirable... or not.
Solution 5 is interesting because the file is never locked by thread/process aware of the locking scheme will safely read/write the file.
There are probably other locking schemes. The developer has to carefully think about his intent and use case. And of course must fully understand how locking files works. The file locking is the base of multi user applications and exists almost since the beginning of computer software and databases. There are a lot of articles and books published on the subject.