Thread.Sleep(0) doesn't work as described?

霸气de小男生 提交于 2019-12-19 16:54:22

问题


I am currently reading this excellent article on threading and read the following text:

Thread.Sleep(0) relinquishes the thread’s current time slice immediately, voluntarily handing over the CPU to other threads.

I wanted to test this and below is my test code:

static string s = "";

static void Main(string[] args)
{
    //Create two threads that append string s
    Thread threadPoints = new Thread(SetPoints);
    Thread threadNewLines = new Thread(SetNewLines);

    //Start threads
    threadPoints.Start();
    threadNewLines.Start();

    //Wait one second for threads to manipulate string s
    Thread.Sleep(1000);

    //Threads have an infinite loop so we have to close them forcefully. 
    threadPoints.Abort();
    threadNewLines.Abort();

    //Print string s and wait for user-input
    Console.WriteLine(s);
    Console.ReadKey();
}

The functions that threadPoints and threadNewLines run:

static void SetPoints()
{
    while(true)
    {
        s += ".";
    }
}

static void SetNewLines()
{
    while(true)
    {
        s += "\n";
        Thread.Sleep(0);
    }
}

If I understand Thread.Sleep(0) correctly, the output should be something like this:

............        |
..............      |
................    | <- End of console
..........          |
.............       |
...............     |

But I get this as output:

....................|
....................|
....                |
                    |
                    |
....................|
....................|
.................   |
                    |

Seeing as the article mentioned in the beginning of the post is highly recommended by many programmers, I can only assume that my understanding of Thread.Sleep(0) is wrong. So if someone could clarify, I'd be much obliged.


回答1:


What thread.sleep(0) is to free the cpu to handle other threads, but that doesn't mean that another thread couldn't be the current one. If you're trying to send the context to another thread, try to use some sort of signal.




回答2:


If you have access to a machine (or perhaps a VM) with only a single core/processor, try running your code on that machine. You may be surprised with how the results vary. Just because two threads refer to the same variable "s", does not mean they actually refer to the same value at the same time, due to various levels of caching that can occur on modern multi-core (and even just parallel pipeline) CPUs. If you want to see how the yielding works irrespective of the caching issues, try wrapping each s += expression inside a lock statement.




回答3:


If you'd expand the width of the console to be 5 time larger than current then you'd see what you expect, lines not reaching the console width. The problem is one time slice is actually very long. So, to have the expected effect with normal console with you'd have to slow down the Points thread, but without using Sleep. Instead of while (true) loop try this

for (int i = 0;; i++)
{
  if (int % 10 == 0)
    s += ".";
}

To slow down the thread even more replace number 10 with bigger number.




回答4:


The next thread the processor handles is random thread and it even could be the same thread you just called Thread.Sleep(0). To ensure that next thread will be not the same thread you can call Thread.Yield() and check it's return result - if os has another thread that can run true will be returned else false.




回答5:


You should (almost) never abort threads. The best practice is to signal them to die (commit suicide).

This is normally accomplished by setting some boolean variable and the threads should inspect its value to whether continue or not its execution.

You are setting a string variable named "s". You will incur in race conditions. String is not thread safe. You can wrap the operations that manipulate it in a lock or use a built-in type that is thread-safe.

Always pay attention, in the documentation, to know if the types you use are thread-safe.

Because of this you can't rely on your results because your program is not thread-safe. If you run the program several times my guess is that you'll get different outputs.

Note: When using a boolean to share some state to cancel threads, make sure it is marked as volatile. JIT might optimize the code and never looks at its changed value.



来源:https://stackoverflow.com/questions/17365502/thread-sleep0-doesnt-work-as-described

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!