Yes, to protect access to data, you undoubtedly need semaphores (or something similar, for example, an event or a critical section).
My immediate reaction would be to think primarily about the sequence of blocks, but not about the complete file. Secondly, I almost never use a semaphore (or something like that) directly. Instead, I would usually use a thread-safe queue, so when a network stream reads a block, it places the structure in a queue where data is indicated, etc. A processing thread expects an element in the queue, and when it arrives, it pops up and processes this block.
When it finishes processing a block, it usually displays the result in another queue for the next processing step (for example, writes to a file) and (quite possibly) places the handle of the processed block in another queue, so memory can be reused to read another input block.
At least in my experience, this type of design eliminates a large percentage of thread synchronization problems.
Edit: I'm not sure how to create a thread-safe queue, but I posted the code for easy in the previous answer.
Regarding design patterns, I saw that this is called at least βconveyorβ and βproduction lineβ (although I'm not sure I saw the latter in a lot of literature).
source share