Example of fork and mutex lock process in Linux multithreading

Example of fork and mutex lock process in Linux multithreading

Question:

We have such a problem: create a child process in a multi-threaded program and let子線程and子進程acquire a lock of a global variable, the output child thread gets the lock, then unlocks it, the child process gets the lock, and then unlocks it;

1. First attempt

Code:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/wait.h>

pthread_mutex_t mutex;

void* fun(void* arg)
{
	pthread_mutex_lock(&mutex);	
	printf("fun get lock\n");
	sleep(3);

	pthread_mutex_unlock(&mutex);
	printf("fun unlock\n");
}
int main()
{
	pthread_mutex_init(&mutex, NULL);
	pthread_t id;
	pthread_create(&id, NULL, fun, NULL);
	
	sleep(1);
	pid_t pid = fork();
	if(pid == -1)
	{
		perror("fork err");
		return -1;
	} 

	if(pid == 0)
	{
		pthread_mutex_lock(&mutex);	
		printf("child get lock\n");
		sleep(3);
		
		pthread_mutex_unlock(&mutex);
		printf("child unlock\n");
		exit(0);
	}
	
	wait(NULL);

	pthread_mutex_destroy(&mutex);
	printf("main over\n");
	return 0;
}

Conjecture results:

Sort out your thoughts:

Create a global lock and initialize it
The main thread creates a child thread to acquire the lock. The main thread sleeps for one second, and the child thread gets the lock and locks it.
The child thread sleeps for 3 seconds, outputs unlock fun, and the child thread exits
The main thread starts forking, the child process gets the lock, and outputs child lock
Child process unlock output child unlock
The main thread of the parent process waits for the child process to exit, and finally destroys the lock and outputs main over
So… get straight to the correct code! ! !

2. Rational Analysis

Unfortunately, the answer is wrong! ! !

我們先來康康運行結果:正常輸出了子線程的內容,但是。。。。卡住了?沒錯阻塞了。。

insert image description here

Analyze again:

block? ? Could it be that the child process is blocked when acquiring the lock? Or is the parent process blocked waiting for the child process?
In other words: both places are blocked, the child process is blocked when acquiring the lock, causing the parent process to be blocked.
Verify it! !

insert image description here

So the program is blocked in two places. The child process is blocked when acquiring the lock, causing the parent process to be blocked.

3. Problem Solving

實際上,我們子線程在獲取這把鎖并加鎖后睡眠3秒,主線程睡眠1秒,在主線程1秒睡眠結束后,開始執行fork,此時的子線程還未解鎖正處于睡眠狀態,fork過程中,會直接復制父進程的所有資源(**包括這把鎖、鎖的狀態**),沒錯

就是有兩把鎖。此時子線程進行了加鎖的狀態,所以子線程復制的鎖也是加鎖狀態。所以子線程會正常退出,而子進程會因為拿到加鎖的鎖而阻塞,父進程wait因為子進程阻塞而阻塞;

(1) Using pthread_join()

Use pthread_join() before fork. Before the child thread ends, the main thread will be blocked and wait for the child thread to end before forking. At this time, the lock obtained by the child process is unlocked.

Code:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/wait.h>

pthread_mutex_t mutex;

void* fun(void* arg)
{
	pthread_mutex_lock(&mutex);	
	printf("fun get lock\n");
	sleep(3);

	pthread_mutex_unlock(&mutex);
	printf("fun unlock\n");
}
int main()
{
	pthread_mutex_init(&mutex, NULL);
	pthread_t id;
	pthread_create(&id, NULL, fun, NULL);
	pthread_join(id, NULL);
	
	sleep(1);

	pid_t pid = fork();
	if(pid == -1)
	{
		perror("fork err");
		return -1;
	} 

	if(pid == 0)
	{
		pthread_mutex_lock(&mutex);	
		printf("child get lock\n");
		sleep(3);

		pthread_mutex_unlock(&mutex);
		printf("child unlock\n");
		exit(0);
	}
	
	wait(NULL);

	pthread_mutex_destroy(&mutex);
	printf("main over\n");
	return 0;
}

result:

insert image description here

(2) Use phread_atfork() to register a pre-fork judgment

Header file: pthread.h

int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));

prepare: This function is called before fork is executed

parent: The parent process calls this function after fork is executed

child: The child process calls this function after fork is executed

Return value: 0 if successful, error code if failed

Code:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/wait.h>

pthread_mutex_t mutex;

void prepare_fun(void)
{
	pthread_mutex_lock(&mutex);
}

void parent_fun(void)
{
	pthread_mutex_unlock(&mutex);
}

void child_fun()
{
	pthread_mutex_unlock(&mutex);
}

void* fun(void* arg)
{
	pthread_mutex_lock(&mutex);	
	printf("fun get lock\n");
	sleep(3);

	pthread_mutex_unlock(&mutex);
	printf("fun unlock\n");
}

int main()
{
	
	pthread_mutex_init(&mutex, NULL);
	pthread_t id;
	pthread_atfork(prepare_fun, parent_fun, child_fun);
	pthread_create(&id, NULL, fun, NULL);
	
	sleep(1);

	pid_t pid = fork();
	if(pid == -1)
	{
		perror("fork err");
		return -1;
	} 

	if(pid == 0)
	{
		pthread_mutex_lock(&mutex);	
		printf("child get lock\n");
		sleep(3);

		pthread_mutex_unlock(&mutex);
		printf("child unlock\n");
		exit(0);
	}
	
	wait(NULL);

	pthread_mutex_destroy(&mutex);
	printf("main over\n");
	return 0;
}

result:

insert image description here

This is the end of this article about the fork and mutex process examples in Linux multithreading. For more relevant Linux multithreading fork and mutex content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Detailed explanation of Python garbage collection mechanism
  • Python language development garbage collection mechanism principle tutorial
  • Analysis of the principle of Python garbage collection mechanism
  • How is Python garbage collection implemented?
  • Introduction to fork in multithreading under Linux
  • Python Garbage Collection and Linux Fork

<<:  Implementation of CSS linear gradient concave rectangle transition effect

>>:  How to get the dynamic number of remaining words in textarea

Recommend

The difference and execution method of select count() and select count(1)

Count(*) or Count(1) or Count([column]) are perha...

Detailed explanation of using split command to split Linux files

A few simple Linux commands let you split and rea...

CentOs7 64-bit MySQL 5.6.40 source code installation process

1. Install the dependency packages first to avoid...

Analysis of the principles and usage of Docker container data volumes

What is a container data volume If the data is in...

Native JavaScript to implement random roll call table

This article example shares the specific code of ...

Detailed explanation of CocosCreator MVC architecture

Overview This article will introduce the MVC arch...

WeChat applet component development: Visual movie seat selection function

Table of contents 1. Introduction 1. Component da...

HTML tutorial, HTML default style

html , address , blockquote , body , dd , div , d...

React Principles Explained

Table of contents 1. setState() Description 1.1 U...

Detailed explanation of Nginx status monitoring and log analysis

1. Nginx status monitoring Nginx provides a built...

How to configure ssh/sftp and set permissions under Linux operating system

Compared with FTP, SSH-based sftp service has bet...

The magic of tbody tag speeds up the display of table content

You must have saved other people’s web pages and l...

Two implementation codes of Vue-router programmatic navigation

Two ways to navigate the page Declarative navigat...