Some people explain the difference between a thread and a process in this way: 2
Thread: minimum unit of Resource Competition2.
Process: minimum unit of Resource AllocationFrom the perspective of resource management, threads and processes are well separated. Here, we will not go into the details about how each specific platform implements a thread or process. Here we only need to understand that the crash of a process generally does not affect other processes running on the same system as it, the death of a thread is related to other threads in the same process as the thread. Generally, the system provides APIs in the C format of the registration thread as follows (Java and other built-in tasks are not mentioned here ):
// Function: register a thread // para: char * threadname thread name // void (* Fun) (void *) thread callback function // void * para callback function entry parameter void reg_thread (char * threadname, void (* Fun) (void *), void * para); // function: cancel a thread // para: char * threadname the thread name void unreg_thread (char * threadname ); |
These two interfaces are simple and clear. I can write my lower thread:
# Define free (s) do {/free (s);/S = NULL;/} while (0) void fun (void * para ){...... While (true) {dosomething ()}} |
Void * para = malloc (1 <10); reg_thread ("even thread", fun, para );...... If (I want to stop this thread) unreg_thread ("even thread"); free (para );...... |
It is true that your thread startup may also achieve some of your goals, but note that your code has a hidden risk, which is caused by the logout statement. "Logout? Unreg_thread ("Even thread ");?" Yes, a strong thread deregister may cause resource leakage.
Void fun (void * para ){Void * P = malloc (1 <10); // For example, you have applied for a resourceWhile (true) {dosomething ()}Free (p); // release it here} |
Although you are very careful, the memory you open is indeed lost with the thread's extinction! Because the APIS provided by the system for thread cancellation generally do not guarantee that your function will be executed normally to the end. In fact, the code above has no foundation. You are an endless loop and cannot be transferred. Here I want to explain one thing: 2
There are two types of resources in the program: one is managed by the system for you, the other is not responsible for the life and death cycle of the system, and the other is lent to you by the system, it is the most basic character to pay off a loan and complete it.
Note:The resources here include the memory you dynamically applied for, the semaphore you applied for, and the thread you created. If you do that, you will lose people's things and lose yourself a certain character. What should you do? Modify the solution! Modify and add the Code as follows:
Bool g_blflag = true; // Add a global variable.# Define unreg_thread (s) g_blflag = false // Add a macro to replace the API that the system gave me to make me lose my characterVoid fun (void * para) {void * P = malloc (1 <10); // For example, you have applied for a resource while (G_blflag)// Use a variable to control this loop.{Dosomething ()} Free (p); // release here} |
"Now the program has safely released the resources. ^ _ ^, the memory can be safely released, and my character is saved !" Haha, don't be happy too early. The hidden danger is not over yet! "Not over yet ?" Yes. Let's look back at the registration function.
...... Void * para = malloc (1 <10); reg_thread ("even thread", fun, para );...... If (I want to stop this thread) unreg_thread ("even thread ");Free (para); // does the thread really jump out of the loop body at this time?...... |
When we set the loop flag to false, when I applied for memory free, did the even thread really end? The answer is: I don't know! Yes, you have no way to predict when the thread will actually exit the stage of resource competition. Let's try again! We can use a semaphore to notify us, so we get the following code:
Bool g_blflag = true; // Add a global variable.Semaphore semaphore;# Define unreg_thread (s) do {g_blflag = false;/P (semaphore);} while (0)Void fun (void * para ){P (semaphore );Void * P = malloc (1 <10); // For example, you have applied for a resource while (g_blflag) // use a variable to control this loop. {dosomething ()} Free (p); // release it here.V (semaphore );} |
First, we create a mutex semaphores. The semaphores are obtained and released upon exit as soon as they enter the thread execution body. The logout action will also wait for the semaphores to be executed. Is it safe? "……?" Tick, tick, tick ...... Our end thread action is waiting like your thoughts. What are you waiting? Why does the thread still not exit? Let's look at the following:
...... Void fun (void * para) {P (semaphore); void * P = malloc (1 <10); // For example, you have applied for a resource while (g_blflag) // use a variable to control this loop {Dosomething () // What is the action here? Sleep (2 minutes );} Free (p); // release V (semaphore) here );} |
If there is a function execution body that is similar
Sleep (2 minutes)What should I do with such an action? What's more terrible is what should I do when the select blocking type waits for semaphores in network programs? In this case, how can we ensure that he exits faster? The action of my end thread cannot be too concession !! To rewrite this function, we replaced the system call with a function of our own. We have done a lot with macros before, this time we still use this easy-to-use method to achieve our goal! The adaptation is as follows:
Void sleep (DWORD time); // assume this is the call void mysleep (DWORD time) provided by the system {If (time less than 1 second) // here is the waiting duration limit for our end thread {return sleep (time);} splits the time into n do {sleep (1 second);} while (g_blflag) & (-- N ));}# Define sleepMysleep |
For the above adaptation, we use our own functions to replace the functions provided by the system. This solves our waiting problem. Other functions can be adapted similarly to ipv_^. Don't be too happy! Hidden risks still exist:
...... Unreg_thread ("Even thread ");......Sleep (2 minutes); // I want to wait for two minutes !! |
What should you do if you want to call this sleep somewhere else after you end the thread? I wanted to let it go to bed for 2 minutes and it ran out in 1 second! You will not always add g_blflag = true before other calls; to control it! What should I do? After a while, I came up with inspiration.
# Define sleep (s) if (G_blsleepflag )///Add another variable to control the call!Mysleep (s );/Else/Sleep (s) # Define reg_thread g_blsleepflag = true; reg_thread // This is also applicable # Define unreg_thread (s) do {g_blflag = false ;/P (semaphore );/G_blsleepflag = false;} while (0) Bool g_blsleepflag = true; // Add this variable ...... Unreg_thread ("Even thread ");......Sleep (2 minutes); // I can call back the sleep !! |
By adding a new global variable, you can solve this small problem ^ _ ^ ,...... Is it safe ......? Let's take a look at it!
Reg_thread ("even thread 1", fun, para); reg_thread ("even thread 2", fun, para );...... If (I want to stop this thread 1) unreg_thread ("even thread 1 ");// I just want to end thread 1, but the bad thing is that thread 2 also exits !!!!...... |
If you register two threads like this, when you end one of them, the other end, but the other may be blocked, it's all messy. # ◎ ¥ % ◎ # × ...... % ※There is a kind of feeling called struggle. How can this problem be solved! Which of the following links has caused me to fall into the quagmire and become deeper and deeper? What we often hear on weekdays: 2
Write code and write reusable code.Why is the poor reusability and scalability of code that is full of tips? Just a few defects will hurt me ...... Stop complaining! Let's continue reading!
Class mythread {public: void run (); void stop (); Private: bool m_blflag; semaphore; private: Virtual void prethread (); Virtual void onthread () = 0; virtual void postthread (); void sleep (DWORD time) {If (time less than 1 second) // here is the maximum waiting patience of our end thread {return :: sleep (time) ;}split the time into N 1-second do {:: sleep (1 second) ;}while (m_blflag) & (-- N ));} static void func (void * para) {mythread * pthis = static_cast <mythread *> (para); If (null = pthis) {return;} pthis-> prethread (); while (pthis-> m_Blflag) {pthis-> onthread () ;}pthis-> postthread ();}}; |
We encapsulate it into a class shelf and start and stop a thread in an object-oriented way. The specific implementation in it is reserved for readers who are interested to fill it out by themselves! The task you think of is derived from you. You can adapt to the blocking function as needed. At least in this section, I really don't want to talk about it as there are potential risks, because I have to take a break. Summary: I feel like speaking of the header, I am trying to persuade a C programmer to switch to C ++ ^_^.