1. reentrant function
A function is reentrant if it can be safely recursive or called in parallel. To become a reentrant function, the function cannot contain (or use) static (or global) data (to store state information during a function call), nor can it return a pointer to static data, which can only use the data provided by the caller, and certainly not the non-reentrant function.
More typical non-reentrant functions are Getpwnam, strtok, malloc, etc.
Examples of reentrant and non-reentrant functions
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <math.h>
int* getpower (int i)
{
static int result;
result = POW (2, i);
GetChar ();
Return &result;
}
int main ()
{
int *result;
struct Sigaction sa;
memset (&sa, 0, sizeof (SA));
Sa.sa_handler = &handler;
Sigaction (SIGALRM, &sa, NULL);
result = Getpower (5);
printf ("2^5 =%d\n", *result);
return 0;
}
Test method:
1. Compile GCC Test.c-lpthread
Run in a terminal./a.out, running Ps-a|grep a.out in another terminal can see the ID of the process
2. Run a.out in the following ways:
Run./a.out, run the kill-14 PID in another terminal before pressing the carriage return (the PID is the value you see when running the above PS)
Then, press ENTER to continue running a.out will see 2^5 = 8 Error Conclusion
For functions int* getpower (int i)
Because the function getpower returns a pointer to the static data, and calls Getpower again in the first call to Getpower, the two-time pointer points to the same memory, and the second result will be overwritten for the first time ( This use of many non-reentrant functions can lead to uncertain consequences. So it's non-reentrant.
for function void Getpower_r (int i, int* result)
Getpower_r stores the resulting information in the memory indicated by result, which uses only the data provided by the caller, so it is reentrant. It can be used normally in signal processing functions.
2. Thread-safe function Thread safety is a concept in multithreaded programming where the thread safe function refers to functions that can be executed correctly concurrently by multiple threads.
Examples of thread safe and non thread safe
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void* func_s (void* unused)
{
Pthread_mutex_lock (&sharedmutex); /* Enter critical section/*
if (count = = 0)
count++;
Pthread_mutex_unlock (&sharedmutex); /* Leave the critical area * *
}
int main ()
{
pthread_t Pid1, Pid2;
Pthread_create (&PID1, NULL, &FUNC, NULL);
Pthread_create (&pid2, NULL, &FUNC, NULL);
Pthread_join (PID1, NULL);
Pthread_join (Pid2, NULL);
return 0;
}
The function func is non thread safe because it does not avoid the race condition of the shared data count.
Imagine this scenario: first count is 0, and when thread 1 goes into the Func function, after the Count = 0 is judged, thread 2 enters the Func function
Thread 2 judges Count==0 and executes count++, then thread 1 begins execution, at which point Count!= 0, but thread 1 still has to execute
count++, this creates an error.
This can be avoided by func_s access to the shared data through a mutex lock. func_s is thread safe.
As long as the proper "lock" mechanism, the thread safe function is still relatively good to implement.
3. The difference between the reentrant function and the thread safe function The Reentrant function is independent of multithreading and, if it is a reentrant function, requires that the function be able to operate correctly even if the same process (or thread) enters the function multiple times at a time.
The requirement also implies that the function works correctly in a multithreaded environment when different two threads enter the function at the same time.
The thread safe function is related to multithreading, and it simply requires that a different two-thread call to the function be logically correct.
As can be seen from the above instructions, Reentrant's requirements are more stringent than that of thread safe. Reentrant functions must be thread safe, and the function of thread safe
may not be reentrant. An example is provided:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main ()
{
pthread_t Pid1, Pid2;
struct Sigaction sa;
memset (&sa, 0, sizeof (SA));
Sa.sa_handler = &handler;
Sigaction (SIGALRM, &sa, NULL);
printf ("Main thread ' s PID is:%d\n", pthread_self ());
func_s (NULL);
Pthread_create (&PID1, NULL, &func_s, NULL);
Pthread_create (&pid2, NULL, &func_s, NULL);
Pthread_join (PID1, NULL);
Pthread_join (Pid2, NULL);
func_s (NULL);
return 0;
}
Test method:
1. Compile GCC Test.c-lpthread
Run in a terminal./a.out, running Ps-a|grep a.out in another terminal can see the ID of the process
2. Perform the following 4 run A.out:
Each run in the first 1,2,3,4, in another terminal running KILL-14 PID (the PID here is the value seen above PS)
Test results:
1. There are 3 threads in the process: one main thread, two child threads
2. The func_s is thread safe.
3. func_s not reentrant.
4. Signal handlers interrupt the execution of the main thread without disrupting the execution of the child threads
5. In the 1th, 4 times before return, in another terminal running kill-14 PID will form a deadlock, because
The main thread enters upgradeable the critical section, the main thread is interrupted, the handler is executed (in the main thread), and handler attempts to lock the critical section
Deadlock is formed because the same thread locks two times
6. In the 2nd, 3 times before return, in another terminal running kill-14 PID does not form a deadlock, because a strand enters upgradeable lock
The critical section, when the main thread is interrupted, executes the handler (in the main thread), and when Handler tries to lock the critical section, it is suspended, at which point the child thread
Can be continued. When the child thread releases the lock, handler and another child thread can compete into the critical section and continue execution.
So it doesn't form a deadlock.
Conclusions:
1. Reentrant is a very strict requirement for functions, most of which are not reentrant (Apue has a reentrant function
List).
When do we need the reentrant function? Only one function needs to enter more than two times in the same thread, we need
reentrant function. These situations are mainly asynchronous signal processing, recursive functions, and so on. (Recursive functions of non-reentrant are not necessarily
Error, no error depends on how you define and use the function. Most of the time, we don't need a function to be reentrant.
2. In a multithreaded environment, when only multiple threads can call a function at the same time, the function can be as long as it is thread safe.
Most of our common functions are thread safe, and consult the documentation if you are unsure.
3. The essential difference between reentrant and thread safe is that the reentrant function requires that even if you enter more than two times in the same thread,
can also be executed correctly.
The common malloc function is a typical non-reentrant but is the thread safe function, which means that we can easily
Malloc is called at the same time in multiple threads, but it is a dangerous thing to put the malloc function into a signal processing function.
4. The reentrant function must be the thread safe function, that is to say, non thread safe is definitely the Non-reentrant function
The Non-reentrant function can not be changed into reentrant function simply by adding a lock
The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion;
products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the
content of the page makes you feel confusing, please write us an email, we will handle the problem
within 5 days after receiving your email.
If you find any instances of plagiarism from the community, please send an email to:
info-contact@alibabacloud.com
and provide relevant evidence. A staff member will contact you within 5 working days.