给群里的;
群里的人问, 多线程下调用fork , 但子进程没办法执行下去了,原因是子进程中也访问了同一把锁;
fork的子进程将继承父进程锁的状态 , 如果fork时此锁已经被锁住了;
一个模拟的例子:
#include "util.h"
#include <signal.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/wait.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void * func1(void *arg)
{
printf("thread start : %ld\n" , pthread_self());
pthread_mutex_lock(&mutex);
puts("thread enter lock");
sleep(5); //睡5秒
pthread_mutex_unlock(&mutex);
}
int main(int argc, char**argv)
{
pthread_t t1;
pthread_create(&t1,0,func1,NULL);
sleep(1);
int pid = fork();
if(0 == pid){
//子进程
//解决办法是不管有没有锁住,先解锁再说
//pthread_mutex_unlock(&mutex);
puts("child begin");
//由于此时的mutex 是被锁住的, 因此,子进程将永远等在这里
pthread_mutex_lock(&mutex);
puts("??????????");
pthread_mutex_unlock(&mutex);
return 0;
}
//parent
pthread_join(t1,0);
puts("begin wait child");
wait(NULL);
return 0;
}
代码中注释的是解决办法之一
另一种是 pthread_atfork:
#include "util.h"
#include <signal.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/wait.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void * func1(void *arg)
{
printf("thread start : %ld\n" , pthread_self());
pthread_mutex_lock(&mutex);
puts("thread enter lock");
sleep(5);
pthread_mutex_unlock(&mutex);
}
void prepare(){
puts("preapre");
pthread_mutex_lock(&mutex);
}
void parent_handler(){
puts("parent handler");
pthread_mutex_unlock(&mutex);
}
void child_handler(){
puts(" ---------- child handler");
pthread_mutex_unlock(&mutex);
}
int main(int argc, char**argv)
{
pthread_t t1;
pthread_create(&t1,0,func1,NULL);
pthread_atfork(0,0,child_handler); //统一处理锁的问题
sleep(1);
int pid = fork();
if(0 == pid){
puts("child begin");
pthread_mutex_lock(&mutex);
puts("??????????");
pthread_mutex_unlock(&mutex);
return 0;
}
//parent
pthread_join(t1,0);
puts("begin wait child");
wait(NULL);
return 0;
}
上面代码中只用了child_handler, 在子进程一开始就调用了;
另2个参数;
// prepare 在fork调用之前就被调用
// parent_handler在fork返回父进程前被调用
pthread_atfork(prepare,parent_handler,child_handler);