You can always be perverted in different ways, but I would like a better understanding of what is more appropriate to apply in a given situation.
I have my own little vision. For example, if you need to protect against simultaneous access to any data, then mutexes and critical sections will do, but critical sections will be faster, so you need to select them, unless you need access to this object from the second process.
Semaphores are best used when there is a producer stream and a consumer stream, for example, you need to sort the array in ascending order in a separate stream and output each ready element in the main stream.
Events are needed for situations where it is necessary to deduce a lot of threads from the expectation (poorly understand the real use and why it is not easier to do the same with semaphores or mutexes).
In general, as you can see, according to the knowledge in this matter, I have only the basic stuffing consisting of an incomplete theory and divorced from real practice.