1. Introduction
First clear a question: if a thread of a multithreaded procedure calls the fork function, then the newly created subprocess will not automatically create the same number of threads as the parent process, it is just the full copy of the thread that called the fork. Also, the child process automatically inherits the state of the mutex in the parent process, including the thread that the parent process created before calling fork. In other words, a mutex that has been locked in the parent process is also locked in the child process. This raises the question of whether the child process may not know the specific state of the mutex that inherits from the parent process (the locking state or the unlocked state). This mutex may be locked, but not by the thread that calls the fork function, but by other threads. If this is the case, then the child process will cause a deadlock if it performs a lock operation on the mutex again. Here are a few cases where a child process inherits a parent process mutex.
2. Inherit the lock created by the parent process
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <
Wait.h> pthread_mutex_t Mutex;
int main () {pthread_mutex_init (&mutex,null);
Pthread_mutex_lock (&mutex);
int pid = fork ();
if (pid<0) {pthread_join (id,null);
Pthread_mutex_destroy (&mutex);
return 1;
} else if (PID = = 0) {printf ("I am in the child,want to get the lock\n");
Pthread_mutex_lock (&mutex);
printf ("I am Running here,oop...\n");
Pthread_mutex_unlock (&mutex);
printf ("I unlocked\n");
Exit (0);
} else {sleep (3);
Pthread_mutex_unlock (&mutex);
printf ("unlocked\n");
Wait (NULL);
} pthread_join (Id,null);
Pthread_mutex_destroy (&mutex);
return 0; }
Deadlock. As you can see, the parent process is preceded by a lock, the child process inherits the state of the locking, when the attempt to lock is blocked, even if the 3 second stepfather process unlocked, the child process is still unable to lock operation, because the child process after the fork is invisible to the parent process, so the child process is stuck in a permanent blocking state.
3. Child threads of the parent process perform a lock operation before fork
#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <stdlib.h> #include <
Wait.h> pthread_mutex_t Mutex;
void* another (void* Arg) {printf ("in Child thread\n");
Pthread_mutex_lock (&mutex);
printf ("lock\n");
Sleep (5);
Pthread_mutex_unlock (&mutex);
printf ("Unlocked the mutex\n");
} int main () {pthread_mutex_init (&mutex,null);
pthread_t ID;
Pthread_create (&id,null,another,null);
Sleep (1);
int pid = fork ();
if (pid<0) {pthread_join (id,null);
Pthread_mutex_destroy (&mutex);
return 1;
} else if (PID = = 0) {printf ("I am in the child,want to get the lock\n");
Pthread_mutex_lock (&mutex);
printf ("I am Running here,oop...\n");
Pthread_mutex_unlock (&mutex);
printf ("I unlocked\n");
Exit (0);
} else {wait (NULL);
} pthread_join (Id,null); Pthread_mutex_destroY (&mutex);
return 0; }
Deadlock. 1 Seconds of sleep before the fork is to allow the child thread to perform the lock first. As you can see, after the Cheng, the child process inherits the state of the mutex, cannot perform the lock operation, and is blocked. The child process continues to block even after the child thread has been unlocked. Indicates that the child process inherits only the state of the lock and is not visible to subsequent unlock actions.
4. Child threads after fork locking
#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <stdlib.h> #include <
Wait.h> pthread_mutex_t Mutex;
void* another (void* Arg) {printf ("in Child thread\n");
Sleep (2);
Pthread_mutex_lock (&mutex);
printf ("lock\n");
Pthread_mutex_unlock (&mutex);
printf ("Unlocked the mutex\n");
} int main () {pthread_mutex_init (&mutex,null);
pthread_t ID;
Pthread_create (&id,null,another,null);
int pid = fork ();
if (pid<0) {pthread_join (id,null);
Pthread_mutex_destroy (&mutex);
return 1;
} else if (PID = = 0) {printf ("I am in the child,want to get the lock\n");
Pthread_mutex_lock (&mutex);
printf ("I am Running here,oop...\n");
Sleep (5);
Pthread_mutex_unlock (&mutex);
printf ("I unlocked\n");
Exit (0);
} else {wait (NULL);
} pthread_join (Id,null); Pthread_mutex_deStroy (&mutex);
return 0; }
is normal. The child threads have not been locked before the fork, the child process has been successfully locked, and then the child thread has performed the lock operation, and the two have successfully unlocked the lock. Note that the child process inherits only the state of the lock operation that was performed by the parent process (including its child threads) before the fork, and the parent-child operation of the lock is not visible.
5. A thread created by a child thread executes locking
#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <stdlib.h> #include <
Wait.h> pthread_mutex_t Mutex;
void* another (void* Arg) {printf ("in Child thread\n");//Sleep (2);
Pthread_mutex_lock (&mutex);
printf ("lock\n");
Sleep (5);
Pthread_mutex_unlock (&mutex);
printf ("Unlocked the mutex\n");
} void* Childpthread (void* Arg) {pthread_t thid;
Pthread_create (&thid,null,another,null);
Pthread_join (Thid,null);
} int main () {pthread_mutex_init (&mutex,null);
pthread_t ID;
Pthread_create (&id,null,childpthread,null);
Sleep (3);
int pid = fork ();
if (pid<0) {pthread_join (id,null);
Pthread_mutex_destroy (&mutex);
return 1;
} else if (PID = = 0) {printf ("I am in the child,want to get the lock\n");
Pthread_mutex_lock (&mutex);
printf ("I am Running here,oop...\n");
Sleep (5); Pthread_muTex_unlock (&mutex);
printf ("I unlocked\n");
Exit (0);
} else {wait (NULL);
} pthread_join (Id,null);
Pthread_mutex_destroy (&mutex);
return 0; }
Deadlock. The state of the lock still the quilt process has inherited.