最近开始学习新的知识啦,哈哈。

C++11开始支持多线程编程,之前多线程编程都需要系统的支持,在不同的系统下创建线程需要不同的API。 如今就可以统一使用C++11的std::thread来处理了。

看下面的例子:

#include <iostream>
#include <windows.h>
#include <thread>

void test(const std::string& str, int time)
{
    for (int i = 0; i < 10; i++)
    {
        Sleep(time);
        std::cout << str.c_str() << i << std::endl;
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::thread t1(test, "t1", 1000);
    std::thread t2(test, "t2", 1500);
    t1.join();
    t2.join();

    char ch;
    std::cin >> ch;
    return 0;
}

运行结果如下: 结果1

Tip: 无论在windows中,还是Posix中,主线程和子线程的默认关系是:

无论子线程执行完毕与否,一旦主线程执行完毕退出,所有子线程执行都会终止。这时整个进程结束或僵死(部分线程保持一种终止执行但还未销毁的状态,而进程必须在其所有线程销毁后销毁,这时进程处于僵死状态),在第一个例子的输出中,可以看到子线程还来不及执行完毕,主线程的main()函数就已经执行完毕,从而所有子线程终止。

需要强调的是,线程函数执行完毕退出,或以其他非常方式终止,线程进入终止态(请回顾上面说的线程状态),但千万要记住的是,进入终止态后,为线程分配的系统资源并不一定已经释放,而且可能在系统重启之前,一直都不能释放。终止态的线程,仍旧作为一个线程实体存在与操作系统中。(这点在win和unix中是一致的。)而什么时候销毁线程,取决于线程属性。 通常,这种终止方式并非我们所期望的结果,而且一个潜在的问题是未执行完就终止的子线程,除了作为线程实体占用系统资源之外,其线程函数所拥有的资源(申请的动态内存,打开的文件,打开的网络端口等)也不一定能释放。所以,针对这个问题,

主线程和子线程之间通常定义两种关系:

可会合(joinable)。这种关系下,主线程需要明确执行等待操作。在子线程结束后,主线程的等待操作执行完毕,子线程和主线程会合。这时主线程继续执行等待操作之后的下一步操作。主线程必须会合可会合的子线程,Thread类中,这个操作通过在主线程的线程函数内部调用子线程对象的wait()函数实现。这也就是上面加上三个wait()调用后显示正确的原因。必须强调的是,即使子线程能够在主线程之前执行完毕,进入终止态,也必需显示执行会合操作,否则,系统永远不会主动销毁线程,分配给该线程的系统资源(线程id或句柄,线程管理相关的系统资源)也永远不会释放。

相分离(detached)。顾名思义,这表示子线程无需和主线程会合,也就是相分离的。这种情况下,子线程一旦进入终止态,系统立即销毁线程,回收资源。无需在主线程内调用wait()实现会合。Thread类中,调用detach()使线程进入detached状态。这种方式常用在线程数较多的情况,有时让主线程逐个等待子线程结束,或者让主线程安排每个子线程结束的等待顺序,是很困难或者不可能的。所以在并发子线程较多的情况下,这种方式也会经常使用。

缺省情况下,创建的线程都是可会合的。可会合的线程可以通过调用detach()方法变成相分离的线程。但反向则不行。