What is the use of Thread.sleep(0)?

We may often use the Thread.Sleep function to suspend the thread for a period of time. So do you correctly understand the usage of this function?

Consider the following two questions:

Question one

Assuming it is 2020-4-7 12:00:00.000, if I call Thread.Sleep(1000), will this thread be awakened at 2020-4-7 12:00:01.000?

Question two

Someone's code used a seemingly inexplicable sentence: Thread.Sleep(0). Since it is Sleep 0 milliseconds, is there any difference compared to removing this code?

review

Let's review the operating system principle first.

In the operating system, there are many strategies for CPU competition.
Unix systems use a time slice algorithmWindows is preemptive

Time slice algorithm

In the time slice algorithm , all processes are arranged in a queue. According to their order, the operating system allocates a period of time to each process, that is, the time that the process is allowed to run.

If the process is still running at the end of the time slice, the CPU will be deprived and assigned to another process. If the process blocks or ends before the time slice ends, the CPU switches immediately. All the scheduler has to do is maintain a list of ready processes, and when the process runs out of its time slice, it is moved to the end of the queue.

Preemptive

A preemptive operating system means that if a process gets the CPU time, it will completely occupy the CPU unless it gives up using the CPU by itself.

Therefore, it can be seen that in a preemptive operating system, the operating system assumes that all processes are of "good character" and will voluntarily exit the CPU.

In a preemptive operating system, assuming there are several processes, the operating system will calculate a total priority for them based on their priority and starvation time (how long it has not used the CPU).
The operating system will hand over the CPU to the process with the highest overall priority.
When the process is finished or hangs on its own initiative, the operating system will recalculate the total priority of all processes once, and then pick the one with the highest priority to give him control of the CPU.

For example

We describe these two algorithms with a cake-sharing scenario.

Suppose there is a steady stream of cake (a steady stream of time), a knife and fork (a CPU), and 10 people waiting to eat the cake (10 processes).

Unix operating system is responsible for dividing the cake

If the Unix operating system is responsible for dividing the cake, then he will set the rules like this:

Everyone came up to eat for 1 minute, and when it was time to change to the next one. When the last person finishes eating, start over again.
So, regardless of whether the 10 people have different priorities, different levels of hunger, and different appetites, everyone can eat for 1 minute when they come up.
Of course, if someone is not too hungry or has a small appetite and is full after eating for 30 seconds, then he can tell the operating system: I am full (hang up). So the operating system will let the next person follow.

The Windows operating system is responsible for dividing the cake

If the Windows operating system is responsible for dividing the cake, then the scene is very interesting. He will make rules like this:

I will calculate a priority for each of you based on your priority and hunger level. The person with the highest priority can come up to eat the cake-until you don't want to eat it.
After this person has finished eating, I will recalculate the priority of each person based on the priority and hunger level, and then assign it to the person with the highest priority.
In this way, this scene is interesting-maybe some people are MMs, so they have high priority, so she can come to eat cakes often. Maybe another person is a DD, so the priority is very low, so it's his turn for a long time (because as time goes on, he will become more and more hungry, so the calculated total priority will be higher and higher , So one day it will be his turn).
Moreover, if a big fat man accidentally gets a knife and fork, because he has a big appetite, he may occupy the cake and eat it for a long time, causing the person next to him to swallow. . .
Moreover, there may be such a situation: the result calculated by the operating system now, the overall priority of MM No. 5 is the highest, and it is much higher than others. So I called No. 5 to eat the cake. No. 5 ate for a while, feeling less hungry, so he said "I will not eat anymore" (hang up).
Since May 5 has just eaten, her hunger level has become smaller, so her overall priority has become smaller;
while other people have waited a while and their hunger levels have become greater, so their overall priority has also become larger.
However, at this time, it is still possible that the priority of No. 5 is higher than the others, but now it is only slightly higher than the others-but she still has the highest priority in total. Therefore, the operating system will say: No. 5 mm comes up to eat cake... (No. 5 mm is depressed, hasn't it just been eaten..., it has obtained such a high priority).

So, what does the Thread.Sleep function do? Also use the scene of dividing the cake just now to describe.
In the above scene, after MM No. 5 ate the cake once, she felt that she was 8 points full. She felt that she would not want to eat cake again in the next half an hour, so she would tell the operating system: Don't ask me to come up to eat cakes in the next half an hour.

In this way, when the operating system recalculates the total priority of everyone in the following half an hour, it will ignore the 5th mm.The Sleep function does this. He tells the operating system "I will not participate in CPU competition in the next few milliseconds."

to sum up

After reading the role of Thread.Sleep, let's think about the two questions at the beginning of the article.

Answer one

For the first question, the answer is: not necessarily.

Because you just told the operating system: I don't want to participate in CPU competition in the next 1000 milliseconds.
Then after 1000 milliseconds have passed, maybe another thread is using the CPU at this time, then the operating system will not reallocate the CPU until that thread hangs or ends;
besides, even if it happens to be the operating system’s turn to allocate the CPU at this time , Then the current thread is not necessarily the one with the highest total priority, and the CPU may still be preempted by other threads.

Similarly, Thread has a Resume function, which is used to wake up suspended threads. As mentioned above, this function just "tells the operating system that I will participate in the CPU competition from now on". The call of this function does not immediately make this thread gain control of the CPU.

Answer two

For the second question, the answer is: yes, and the difference is obvious.

Suppose that there is another MM 7 in the cake-dividing scene we have just now, and her priority is very, very high, so the operating system will always call her to eat the cake. Moreover, No. 7 also likes to eat cakes very much, and the appetite is also very big. However, the character of No. 7 is very good, she is very kind, and she thinks after taking a few bites: If there is someone who needs cake more than me now, then I will let him.

Therefore, she can tell the operating system every few bites: Let's recalculate the total priority of everyone. However, the operating system does not accept this recommendation-because the operating system does not provide this interface. So No. 7 mm changed his words: "Don't ask me to come up to eat cake in the next 0 milliseconds." This command is accepted by the operating system, so the operating system will recalculate everyone's total priority at this time-note that this time is calculated together with number 7, because "0 milliseconds has passed". Therefore, if there is no one who needs cake more than No. 7, then No. 7 will still be called to eat cake next time.

summary

Therefore, the role of Thread.Sleep(0) is to "trigger the operating system to immediately restart the CPU competition". The result of the competition may be that the current thread still gains control of the CPU, or it may be replaced by another thread to gain control of the CPU.

This is why we often write a Thread.Sleep(0) in the big loop, because this gives other threads such as Paint thread the power to gain control of the CPU, so that the interface will not be suspended there.
In addition, although the above mentioned that "unless it gives up using the CPU, it will completely occupy the CPU", but this behavior is still restricted-the operating system will monitor your occupation of the CPU, if it finds that a thread is occupying the CPU for a long time The CPU will force this thread to suspend, so in reality there will be no situation where "a thread keeps occupying the CPU". As for the program suspended animation caused by our big loop, it is not because this thread has been occupying the CPU.

In fact, during this period of time, the operating system has been competing for multiple CPUs, but other threads immediately exited within a short time after gaining control of the CPU, so it was the thread's turn to continue executing the loop, so it went again. It took a long time to be forced to hang by the operating system. . . Therefore, when reflected on the interface, it looks as if this thread has been occupying the CPU.

Guess you like

Origin blog.csdn.net/qq_32727095/article/details/113847182