什么时候一个线程“打破”

时间:2012-03-10 16:16:41

标签: c++ multithreading

首先,我是MT的新手,所以我为可能会说的任何愚蠢/明显的事情道歉:)

假设你有windows的这些线程回调函数:

unsigned int __stdcall ThrdFuncA(void* param)
{
    std::wstring s(L"Hello World\n");
    std::wcout << s;
    return 0;
}

unsigned int __stdcall ThrdFuncB(void* param)
{
    std::wcout << L"Hello " << L"World" << std::endl;
    return 0;
}

我注意到的是,当我同时运行4个线程的ThrdFuncA并重新运行100次时,输出总是

Hello World
Hello World
Hello World

但是当我同时运行4个线程的ThrdFuncB并重新运行100次时,输出有时会

Hello WorldHello World

Hello World
Hello World
Hello WorldHello World

Hello World

但这引发了一些问题,特别是因为第一个版本总是有效。 这是否意味着线程在执行外部函数时从不“中断”,但总是完成该函数?这个操作系统特定吗? 什么时候一个线程“破裂”?

3 个答案:

答案 0 :(得分:3)

抢占线程 - 你的C ++示例所具有的那种 - 在任何他们想要的地方中断。因此,它可能是巧合的,可以显示您期望的输出 - 或多或少随机。

这是抢先线程的本质:你可能能够提示(使用yield或一些等价物)这是跳转到另一个线程的好时机,而某些操作可能阻塞并触发另一个线程运行,但是你无法确定何时可以切断你的线程。

在不那么常见或流行的协作线程系统中,所有切换都是在可预测的时间完成的。这是非常方便的,但是当它很好的时候很容易意外阻止线程切换,所以它们不太受欢迎。

答案 1 :(得分:1)

要明确“休息”的含义。在具有4个处理器(每个线程一个)的真正并行系统上,线程永远不会停止执行。每个线程都主动打印到共享资源(在这种情况下是输出缓冲区),并且线程很可能会同时写入输出缓冲区,从而为您提供交错输出。

在单核系统上,在任何给定时刻,操作系统将停止一个线程并运行另一个线程。由于这种情况可能随时发生,因此发送到输出缓冲区(屏幕)的字符串数据可能会出现奇怪的间隔。

看看mutual exclusion。对于共享资源(std :: cout),您可以通过要求线程获取锁来保护代码的关键部分,以便只有一个线程可以一次访问资源。锁定是抢占式多线程系统正确性所必需的。见race conditions

答案 2 :(得分:1)

cout调用可能有一个互斥锁,因此序列化它们。如果你“计算”一个完整的“Hello World \ n”字符串,那么cout方法核心代码将不会因为锁定而被中断并从另一个线程重新进入。这导致字符串的不间断输出。

如果使用子串和换行进行多次调用,则很可能另一个线程将在调用之间锁定,因此“混合”子串和换行符。