Are there situations, for example, during a while loop, where the process has "more" or exclusive rights to the processor?
Well, this is not defined, but it would be crazy.
I can not reproduce your problem. Reducing the waiting time to 2 and 5 seconds (so I do not need to wait forever), the child will first unlock, as expected. (Debian 8, Linux 3.16.1-ck1 [BFS Scheduler, custom] on AMD64)
I would say that your planner behaves very strangely and may just be broken. But as they say, it is never recommended to rely on any specific behavior of the scheduler. Always consider this to be broken and insane, damn it - if your code allows a certain sequence of execution, there will be a scheduler enough to select it. (*)
So use synchronization primitives ( semaphores and mutexes , for example, have common versions for use with different processes - you can also just use pipes in some scenarios) when you need to rely on some synchronization.
edit : add two examples to synchronize processes.
First version (ab) using pipe s:
#include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> int main(int argc, char **argv) { int i = 10000; int parent_done[2]; int child_done[2]; char dummy[1] = { 0 }; int pid; pipe(parent_done); pipe(child_done); /* stdio buffering would lead to intermingled output */ setvbuf(stdout, 0, _IONBF, 0); pid = fork(); if (pid == 0) { close(parent_done[1]); close(child_done[0]); while(i > 50) { if(i%100==0) { if (i < 10000) write(child_done[1], dummy, 1); read(parent_done[0], dummy, 1); } printf("Child: %d\n", i); i--; } } else { close(parent_done[0]); close(child_done[1]); while(i < 15000) { if(i%50==0) { write(parent_done[1], dummy, 1); read(child_done[0], dummy, 1); } printf("Parent: %d\n", i); i++; } } exit(EXIT_SUCCESS); }
Then the same thing using POSIX semaphores (this is IMHO much cleaner because semaphores are meant to be synchronized):
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/mman.h> #include <semaphore.h> #include <unistd.h> struct semaphores { sem_t child_done; sem_t parent_done; }; int main(int argc, char **argv) { int i = 10000; int pid; /* map shared memory for the semaphores */ struct semaphores *sems = mmap(0, sizeof(*sems), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); /* initialize both semaphores as "shared" and with an initial count * of 0 */ sem_init(&sems->parent_done, 1, 0); sem_init(&sems->child_done, 1, 0); /* stdio buffering would lead to intermingled output */ setvbuf(stdout, 0, _IONBF, 0); pid = fork(); if (pid == 0) { while(i > 50) { if(i%100==0) { if (i < 10000) sem_post(&sems->child_done); sem_wait(&sems->parent_done); } printf("Child: %d\n", i); i--; } sem_post(&sems->child_done); } else { while(i < 15000) { if(i%50==0) { sem_post(&sems->parent_done); sem_wait(&sems->child_done); } printf("Parent: %d\n", i); i++; } sem_post(&sems->parent_done); } exit(EXIT_SUCCESS); }
Windows has another API for semaphores, see Semaphore objects on MSDN
(*) edit2 is suitable here: when creating examples, I noticed that stdio buffering prevents sleep. So, maybe even your scheduler behaves badly, but simply implements stdio with very unpredictable behavior when flushing buffers. Of course, these are just wild guesses. What you need to know: all FILE descriptors in C are buffered as part of the stdio library C. These include the predefined descriptors stdin , stdout and stderr . The consequence is that what you see on your output does not necessarily reflect the sequence in which the various threads or processes that are output are created. Unless, of course, you turn off buffering completely, as in my examples.