10

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.

4

5 回答 5

2

什么 thread.sleep(0) 是释放 cpu 来处理其他线程,但这并不意味着另一个线程不能是当前线程。如果您尝试将上下文发送到另一个线程,请尝试使用某种信号。

于 2013-06-28T13:20:14.757 回答
1

如果您可以访问只有一个内核/处理器的机器(或者可能是 VM),请尝试在该机器上运行您的代码。您可能会对结果的变化感到惊讶。仅仅因为两个线程引用相同的变量“s”,并不意味着它们实际上同时引用相同的值,因为现代多核(甚至只是并行管道)CPU 上可能发生不同级别的缓存. 如果您想查看不考虑缓存问题的屈服如何工作,请尝试将每个s +=表达式包装在lock语句中。

于 2013-06-28T13:22:38.290 回答
1

如果您将控制台的宽度扩展为当前的 5 倍,那么您会看到您所期望的,线条未达到控制台宽度。问题是一个时间片实际上很长。因此,要使用普通控制台获得预期效果,您必须减慢 Points 线程,但不使用 Sleep。而不是while (true)循环尝试这个

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

为了进一步减慢线程的速度,将数字 10 替换为更大的数字。

于 2013-07-23T12:47:13.453 回答
0

处理器处理的下一个线程是随机线程,它甚至可以是您刚刚调用 Thread.Sleep(0) 的同一个线程。为了确保下一个线程不是同一个线程,您可以调用 Thread.Yield() 并检查它的返回结果 - 如果 os 有另一个可以运行的线程,则返回 true,否则返回 false。

于 2013-07-23T09:36:49.243 回答
-1

你应该(几乎)永远不要中止线程。最好的做法是向他们发出死亡信号(自杀)。

这通常是通过设置一些布尔变量来完成的,线程应该检查它的值是否继续执行。

您正在设置一个名为“s”的字符串变量。您将在比赛条件下招致。字符串不是线程安全的。您可以将操作它的操作包装在锁中或使用线程安全的内置类型。

在文档中始终注意了解您使用的类型是否是线程安全的。

因此,您不能依赖结果,因为您的程序不是线程安全的。如果您多次运行该程序,我的猜测是您将获得不同的输出。

注意:当使用布尔值共享某些状态以取消线程时,请确保将其标记为volatileJIT 可能会优化代码并且从不查看其更改的值。

于 2013-06-28T13:19:04.637 回答